baseline

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

commit 979c284928e43915f93a863f770e977c2e1532f4
parent 0422f39b741cb9e80362f83f21a5c4ab279d27c3
Author: Mohamed Aslan <maslan@sce.carleton.ca>
Date:   Mon,  9 Jun 2014 19:42:51 -0400

code refactored

* objects (FILE, DIR, COMMIT, ...) now are structures.
* DIR, COMMIT are now loaded in memory :(

Diffstat:
MMakefile | 2+-
Mcmd-branch.c | 41+++++++++++++++++++++++++++--------------
Mcmd-checkout.c | 14--------------
Mcmd-log.c | 73++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------
Mdircache-simple.c | 258+++++++++++++++++++++++++++++++++++++++++++++----------------------------------
Mdircache.h | 8+++++---
Ahelper.c | 68++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Ahelper.h | 25+++++++++++++++++++++++++
Mobjdb-fs.c | 238++++++++++++++++++++++++++++++++++++-------------------------------------------
Mobjdb.h | 25++++++-------------------
Aobjects.c | 227+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aobjects.h | 90+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msession.c | 4++--
Msession.h | 2++
14 files changed, 774 insertions(+), 301 deletions(-)

diff --git a/Makefile b/Makefile @@ -1,7 +1,7 @@ PROG= baseline BINDIR= /usr/bin -SRCS= baseline.c config.c common.c session.c +SRCS= baseline.c config.c common.c session.c objects.c helper.c SRCS+= cmd-add.c cmd-branch.c cmd-checkout.c cmd-commit.c cmd-help.c cmd-init.c cmd-log.c cmd-version.c SRCS+= objdb-fs.c SRCS+= dircache-simple.c diff --git a/cmd-branch.c b/cmd-branch.c @@ -39,22 +39,27 @@ cmd_branch(int argc, char **argv) O_LISTCUR, O_LISTALL, O_CREATE, + O_SWITCH } op = O_LISTCUR; - int ch, error = 0; + int ch, error = 0, exist = 0; struct session s; baseline_session_begin(&s, 0); /* parse command line options */ - while ((ch = getopt(argc, argv, "ac:")) != -1) { + while ((ch = getopt(argc, argv, "c:ls:")) != -1) { switch (ch) { - case 'a': - op = O_LISTALL; - break; case 'c': op = O_CREATE; branch = strdup(optarg); break; + case 'l': + op = O_LISTALL; + break; + case 's': + op = O_SWITCH; + branch = strdup(optarg); + break; default: error = 1; break; @@ -68,6 +73,16 @@ cmd_branch(int argc, char **argv) } switch (op) { + case O_CREATE: + /* create a new branch from the current one */ + if (s.db_ops->branch_create_from(s.db_ctx, branch, s.branch) == EXIT_FAILURE) + errx(EXIT_FAILURE, "error, failed to create branch \'%s\'.", branch); + break; + case O_LISTALL: + /* list all branches */ + if (s.db_ops->branch_ls(s.db_ctx) == EXIT_FAILURE) + errx(EXIT_FAILURE, "error, failed to list branches."); + break; case O_LISTCUR: /* list current branch */ if (s.db_ops->branch_get_head(s.db_ctx, s.branch, &head) == EXIT_FAILURE) @@ -75,15 +90,13 @@ cmd_branch(int argc, char **argv) printf("current branch: %s\nhead: %s\n", s.branch, head); free(head); break; - case O_LISTALL: - /* list all branches */ - if (s.db_ops->branch_ls(s.db_ctx) == EXIT_FAILURE) - errx(EXIT_FAILURE, "error, failed to list branches."); - break; - case O_CREATE: - /* create a new branch from the current one */ - if (s.db_ops->branch_create_from(s.db_ctx, branch, s.branch) == EXIT_FAILURE) - errx(EXIT_FAILURE, "error, failed to create branch \'%s\'.", branch); + case O_SWITCH: + if (s.db_ops->branch_if_exists(s.db_ctx, branch, &exist) == EXIT_FAILURE) + errx(EXIT_FAILURE, "error, failed to query branch."); + if (exist) + s.dc_ops->branch_set(s.dc_ctx, branch); + else + errx(EXIT_FAILURE, "branch \'%s\' does not exist.", branch); break; } diff --git a/cmd-checkout.c b/cmd-checkout.c @@ -31,22 +31,8 @@ extern int dircache_simple_get_ops(struct dircache_ops **); int cmd_branch(int, char **); -/* - * creates a new branch. - */ static int checkout(struct session *s, const char *branch_name) { - int exist; - - /* TODO: branch existence check should be moved to dircache */ - if (s->db_ops->branch_if_exists(s->db_ctx, branch_name, &exist) == EXIT_FAILURE) { - return EXIT_FAILURE; - } - if (exist) - s->dc_ops->checkout(s->dc_ctx, branch_name); - else - errx(EXIT_FAILURE, "branch \'%s\' does not exist.", branch_name); - return EXIT_SUCCESS; } diff --git a/cmd-log.c b/cmd-log.c @@ -18,17 +18,76 @@ #include <stdlib.h> /* EXIT_SUCCESS */ #include "cmd.h" -#include "common.h" +#include "session.h" + +#include "objects.h" int cmd_log(int argc, char **argv) { - const char *ptr = baseline_repo_get_rootdir(); - const char *ptr2 = baseline_repo_get_rootdir(); - if (ptr != NULL) - printf("%s\n", ptr); - if (ptr2 != NULL) - printf("%s\n", ptr2); + 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 = "XXXLARAXXX" + }; + 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/dircache-simple.c b/dircache-simple.c @@ -21,21 +21,26 @@ #include <string.h> /* str*(2), mem*(2) */ #include <unistd.h> /* close(2), rmdir(2), unlink(2) */ +#include <fcntl.h> /* O_* macros */ #include <fts.h> /* fts_*(3) */ #include "defaults.h" #include "config.h" #include "objdb.h" #include "dircache.h" +#include "objects.h" +#include "helper.h" int dircache_simple_get_ops(struct dircache_ops **); static int simple_open(struct dircache_ctx **, struct objdb_ctx *, struct objdb_ops *, const char *, const char *); static int simple_close(struct dircache_ctx *); static int simple_init(struct dircache_ctx *); static int simple_insert(struct dircache_ctx *, const char *); -static int simple_checkout(struct dircache_ctx *, const char *); static int simple_commit(struct dircache_ctx *, const char *); -static int simple_get_branch(struct dircache_ctx *, char **); +static int simple_branch_get(struct dircache_ctx *, char **); +static int simple_branch_set(struct dircache_ctx *, const char *); +static int simple_workdir_get(struct dircache_ctx *, char **); +static int simple_workdir_set(struct dircache_ctx *, const char *); static struct dircache_ops simple_ops = { .name = "simple", @@ -46,8 +51,10 @@ static struct dircache_ops simple_ops = { .insert = simple_insert, .remove = NULL, .commit = simple_commit, - .checkout = simple_checkout, - .get_branch = simple_get_branch, + .branch_get = simple_branch_get, + .branch_set = simple_branch_set, + .workdir_get = simple_workdir_get, + .workdir_set = simple_workdir_set, .fsck = NULL, .compress = NULL, .dedup = NULL @@ -170,8 +177,8 @@ simple_init(struct dircache_ctx *dc_ctx) { char *branch_name = NULL, *branch_path; char *dc_path; - int exist, retval; - size_t size = 0; + char *workdir_fname; + int exist, fd, retval; struct stat s; FILE *branch_fp; @@ -187,21 +194,21 @@ simple_init(struct dircache_ctx *dc_ctx) } } /* check if '.baseline/branch' file exists */ - /* TODO: some of that code should be moved to cmd-init */ + /* TODO: a lot of that code should be moved to is_init() func or cmd-init file */ + /* may be already initialized ... should just return failure? */ if(stat(branch_path, &s) == 0) { - if ((branch_fp = fopen(branch_path, "r")) == NULL) { + if (!S_ISREG(s.st_mode)) { retval = EXIT_FAILURE; goto ret; } - if (getline(&branch_name, &size, branch_fp) == -1) { + if (!(s.st_mode & S_IRUSR) || !(s.st_mode & S_IWUSR)) { retval = EXIT_FAILURE; - free(branch_name); goto ret; } - fclose(branch_fp); } else { asprintf(&branch_name, "%s", DEFAULT_BRANCH); + /* this piece of code does not belong here */ if (dc_ctx->db_ops->branch_if_exists(dc_ctx->db_ctx, branch_name, &exist) == EXIT_FAILURE) { retval = EXIT_FAILURE; free(branch_name); @@ -214,13 +221,21 @@ simple_init(struct dircache_ctx *dc_ctx) retval = EXIT_FAILURE; goto ret; } - fprintf(branch_fp, branch_name); + fprintf(branch_fp, "%s", branch_name); fclose(branch_fp); + free(branch_name); } + /* create '.baseline/workdir' file */ + asprintf(&workdir_fname, "%s/workdir", dc_ctx->repo_baselinepath); + if ((fd = open(workdir_fname, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)) == -1) { + free(workdir_fname); + retval = EXIT_FAILURE; + goto ret; + } + close(fd); ret: free(dc_path); free(branch_path); - free(branch_name); return EXIT_SUCCESS; } @@ -233,6 +248,7 @@ simple_insert(struct dircache_ctx *dc_ctx, const char *path) FILE *fp; FTS *dir; FTSENT *entry; + struct file *file; dc_path = get_dircache_path(dc_ctx); if (stat(path, &s) == -1) @@ -270,8 +286,15 @@ simple_insert(struct dircache_ctx *dc_ctx, const char *path) #endif if (stat(entry->fts_path, &fs) == -1) return EXIT_FAILURE; - if (dc_ctx->db_ops->insert_from_file(dc_ctx->db_ctx, T_FILE, entry->fts_path, &objid) == EXIT_FAILURE) - return EXIT_FAILURE; + /* TODO: baseline_file_new2() */ + file = baseline_file_new(); + file->loc = ON_FS; + if ((file->fd = open(entry->fts_path, O_RDONLY, 0)) == -1) + return EXIT_FAILURE; + dc_ctx->db_ops->insert_file(dc_ctx->db_ctx, file); + close(file->fd); + objid = strdup(file->id); + baseline_file_free(file); #ifdef DEBUG printf("\t ID = %s\n", objid); #endif @@ -295,8 +318,16 @@ simple_insert(struct dircache_ctx *dc_ctx, const char *path) /* it's a file, why the hell would we wait, insert it immediately */ if (stat(path, &fs) == -1) return EXIT_FAILURE; - if (dc_ctx->db_ops->insert_from_file(dc_ctx->db_ctx, T_FILE, path, &objid) == EXIT_FAILURE) + /* TODO: baseline_file_new2() */ + file = baseline_file_new(); + file->loc = ON_FS; + if ((file->fd = open(path, O_RDONLY, 0)) == -1) return EXIT_FAILURE; + dc_ctx->db_ops->insert_file(dc_ctx->db_ctx, file); + close(file->fd); + objid = strdup(file->id); + baseline_file_free(file); + if (mkdirp(dc_path, dir_diff(path, dc_ctx->repo_rootpath)) == EXIT_FAILURE) return EXIT_FAILURE; asprintf(&cache_path, "%s/%s", dc_path, dir_diff(path, dc_ctx->repo_rootpath)); @@ -306,13 +337,14 @@ simple_insert(struct dircache_ctx *dc_ctx, const char *path) } fprintf(fp, "F %s %06o\n", objid, fs.st_mode); fclose(fp); + free(objid); free(cache_path); } return EXIT_SUCCESS; } static int -simple_gen_dindex(struct dircache_ctx *dc_ctx, char **didx) +gen_dindex(struct dircache_ctx *dc_ctx, char **didx) { char *dircache_path, *didx_path = NULL; char *paths[2]; @@ -359,85 +391,12 @@ simple_gen_dindex(struct dircache_ctx *dc_ctx, char **didx) return EXIT_SUCCESS; } -/* TODO: support commits with multiple parents */ -static int -simple_gen_commit(struct dircache_ctx *dc_ctx, const char *dir_id, const char *parent_head, const char *msg_file, char **commit_file) -{ - char *dc_path; - char *cmt_path; - char *msg = NULL; - const char *user_name, *user_email; - int cfd; - size_t size = 0; - struct stat s; - FILE *cfp, *mfp; - - dc_path = get_dircache_path(dc_ctx); - user_name = baseline_config_get_val("username"); - user_email = baseline_config_get_val("useremail"); - if (user_name == NULL || user_email == NULL) - return EXIT_FAILURE; - if (msg_file == NULL) - return EXIT_FAILURE; - if (stat(dc_path, &s) == -1) - return EXIT_FAILURE; - if (!S_ISDIR(s.st_mode)) - return EXIT_FAILURE; - /* commit message */ - if ((mfp = fopen(msg_file, "r")) == NULL) - return EXIT_FAILURE; - /* create commit */ - asprintf(&cmt_path, "%s/commit.XXXXXXX", dc_path); - if ((cfd = mkstemp(cmt_path)) == -1) { - return EXIT_FAILURE; - } - if ((cfp = fdopen(cfd, "w")) == NULL) { - unlink(cmt_path); - close(cfd); - return EXIT_FAILURE; - } - fprintf(cfp, "dir %s\n", dir_id); - if (parent_head != NULL) - fprintf(cfp, "parent %s\n", parent_head); - fprintf(cfp, "author %s <%s>\n", user_name, user_email); - fprintf(cfp, "committer %s <%s>\n", user_name, user_email); - while (getline(&msg, &size, mfp) != -1) { - fprintf(cfp, "%s", msg); - } - fclose(cfp); - fclose(mfp); - *commit_file = cmt_path; - return EXIT_SUCCESS; -} - -static int -simple_get_branch(struct dircache_ctx *dc_ctx, char **branch_name) -{ - char *branch_fname; - size_t size = 0; - FILE *branch_fp; - - asprintf(&branch_fname, "%s/branch", dc_ctx->repo_baselinepath); - *branch_name = NULL; - if ((branch_fp = fopen(branch_fname, "r")) == NULL) { - return EXIT_FAILURE; - } - if (getline(branch_name, &size, branch_fp) == -1) { - free(*branch_name); - return EXIT_FAILURE; - } - fclose(branch_fp); - free(branch_fname); - return EXIT_SUCCESS; -} - static int simple_commit(struct dircache_ctx *dc_ctx, const char *msgfile) { char *cur_branch, *cur_head; char *objid, *path, *paths[2], tmp_objid[1024]; char *dircache_path, *didx_path; - struct objdb_dirhandle *handle; struct stat s; FILE *didx_fp, *fp; FTS *dir; @@ -446,6 +405,9 @@ simple_commit(struct dircache_ctx *dc_ctx, const char *msgfile) size_t size; ssize_t len; char type; + struct dir *ndir; + struct dirent *ent; + struct commit *com; dircache_path = get_dircache_path(dc_ctx); if (stat(dircache_path, &s) == -1) @@ -453,9 +415,10 @@ simple_commit(struct dircache_ctx *dc_ctx, const char *msgfile) if (!S_ISDIR(s.st_mode)) return EXIT_FAILURE; /* FIXME: empty dirache directory */ - simple_gen_dindex(dc_ctx, &didx_path); + gen_dindex(dc_ctx, &didx_path); if ((didx_fp = fopen(didx_path, "r")) == NULL) return EXIT_FAILURE; + objid = NULL; size = 0; path = NULL; /* if not set to NULL, realloc() will get pissed. And, it can waste your day! */ while ((len = getline(&path, &size, didx_fp)) != -1) { @@ -463,7 +426,8 @@ simple_commit(struct dircache_ctx *dc_ctx, const char *msgfile) path[len-1] = 0; --len; } - dc_ctx->db_ops->dir_begin(dc_ctx->db_ctx, &handle); + ndir = baseline_dir_new(); + paths[0] = (char *)path; paths[1] = NULL; if ((dir = fts_open(paths, FTS_NOCHDIR, 0)) == NULL) @@ -481,11 +445,21 @@ simple_commit(struct dircache_ctx *dc_ctx, const char *msgfile) return EXIT_FAILURE; fscanf(fp, "%c %s %o", &type, tmp_objid, &mode); if (type == 'F') { - dc_ctx->db_ops->dir_insert_object(dc_ctx->db_ctx, handle, tmp_objid, entry->fts_name, T_FILE, mode); + ent = (struct dirent *)calloc(1, sizeof(struct dirent)); + ent->id = strdup(tmp_objid); + ent->name = strdup(entry->fts_name); + ent->mode = mode; + ent->type = T_FILE; + baseline_dir_append(ndir, ent); printf("[+] F %06o\t%s\n", mode, entry->fts_name); } else if (type == 'D') { - dc_ctx->db_ops->dir_insert_object(dc_ctx->db_ctx, handle, tmp_objid, entry->fts_name, T_DIR, mode); + ent = (struct dirent *)calloc(1, sizeof(struct dirent)); + ent->id = strdup(tmp_objid); + ent->name = strdup(entry->fts_name); + ent->mode = mode; + ent->type = T_DIR; + baseline_dir_append(ndir, ent); /* FIXME: dir mode are copied from dircache, hence not preserved */ printf("[+] D %06o\t%s\n", mode, entry->fts_name); } @@ -499,7 +473,10 @@ simple_commit(struct dircache_ctx *dc_ctx, const char *msgfile) } } fts_close(dir); - dc_ctx->db_ops->dir_end(dc_ctx->db_ctx, handle, &objid); + dc_ctx->db_ops->insert_dir(dc_ctx->db_ctx, ndir); + free(objid); + objid = strdup(ndir->id); + baseline_dir_free(ndir); #ifdef DEBUG printf("dir \'%s\' commited with ID = %s\n", path, objid); #endif @@ -522,40 +499,99 @@ simple_commit(struct dircache_ctx *dc_ctx, const char *msgfile) return EXIT_FAILURE; } /* get commit's parent */ - if (simple_get_branch(dc_ctx, &cur_branch) == EXIT_FAILURE) + if (simple_branch_get(dc_ctx, &cur_branch) == EXIT_FAILURE) return EXIT_FAILURE; if (dc_ctx->db_ops->branch_get_head(dc_ctx->db_ctx, cur_branch, &cur_head) == EXIT_FAILURE) return EXIT_FAILURE; - /* create commit */ - if (simple_gen_commit(dc_ctx, objid, cur_head, msgfile, &path) == EXIT_FAILURE) - return EXIT_FAILURE; - if (dc_ctx->db_ops->insert_from_file(dc_ctx->db_ctx, T_COMMIT, path, &objid) == EXIT_FAILURE) + if ((com = baseline_helper_commit_build(dc_ctx, objid, cur_head, msgfile)) == NULL) return EXIT_FAILURE; - printf("commit id: %s\n", objid); + dc_ctx->db_ops->insert_commit(dc_ctx->db_ctx, com); + printf("commit id: %s\n", com->id); unlink(path); - dc_ctx->db_ops->branch_set_head(dc_ctx->db_ctx, cur_branch, objid); + dc_ctx->db_ops->branch_set_head(dc_ctx->db_ctx, cur_branch, com->id); free(cur_branch); free(cur_head); free(path); free(objid); + baseline_commit_free(com); return EXIT_SUCCESS; } static int -simple_checkout(struct dircache_ctx *dc_ctx, const char *branch_name) +simple_branch_get(struct dircache_ctx *dc_ctx, char **branch_name) { - char *branch_fname; - FILE *branch_fp; + char *fname; + size_t size = 0; + FILE *fp; - asprintf(&branch_fname, "%s/branch", dc_ctx->repo_baselinepath); - if ((branch_fp = fopen(branch_fname, "w")) == NULL) { + if (dc_ctx == NULL || branch_name == NULL) + return EXIT_FAILURE; + asprintf(&fname, "%s/branch", dc_ctx->repo_baselinepath); + *branch_name = NULL; + if ((fp = fopen(fname, "r")) == NULL) + return EXIT_FAILURE; + if (getline(branch_name, &size, fp) == -1) { + free(*branch_name); return EXIT_FAILURE; } - fprintf(branch_fp, branch_name); - fclose(branch_fp); - /* TODO: copy head files into working dir */ - free(branch_fname); + fclose(fp); + free(fname); return EXIT_SUCCESS; } +static int +simple_branch_set(struct dircache_ctx *dc_ctx, const char *branch_name) +{ + char *fname; + FILE *fp; + + if (dc_ctx == NULL || branch_name == NULL) + return EXIT_FAILURE; + asprintf(&fname, "%s/branch", dc_ctx->repo_baselinepath); + if ((fp = fopen(fname, "w")) == NULL) + return EXIT_FAILURE; + fprintf(fp, "%s", branch_name); + fclose(fp); + free(fname); + return EXIT_SUCCESS; +} + +static int +simple_workdir_get(struct dircache_ctx *dc_ctx, char **commit_id) +{ + char *fname; + size_t size = 0; + FILE *fp; + + if (dc_ctx == NULL || commit_id == NULL) + return EXIT_FAILURE; + asprintf(&fname, "%s/workdir", dc_ctx->repo_baselinepath); + *commit_id = NULL; + if ((fp = fopen(fname, "r")) == NULL) + return EXIT_FAILURE; + if (getline(commit_id, &size, fp) == -1) { + free(*commit_id); + return EXIT_FAILURE; + } + fclose(fp); + free(fname); + return EXIT_SUCCESS; +} + +static int +simple_workdir_set(struct dircache_ctx *dc_ctx, const char *commit_id) +{ + char *fname; + FILE *fp; + + if (dc_ctx == NULL || commit_id == NULL) + return EXIT_FAILURE; + asprintf(&fname, "%s/workdir", dc_ctx->repo_baselinepath); + if ((fp = fopen(fname, "w")) == NULL) + return EXIT_FAILURE; + fprintf(fp, "%s", commit_id); + fclose(fp); + free(fname); + return EXIT_SUCCESS; +} diff --git a/dircache.h b/dircache.h @@ -15,7 +15,7 @@ */ #ifndef _DIRCACHE_H_ -#define _DIRCAHCE_H_ +#define _DIRCACHE_H_ #include <sys/types.h> #include "objdb.h" @@ -36,8 +36,10 @@ struct dircache_ops { int (*insert)(struct dircache_ctx *, const char *); int (*remove)(struct dircache_ctx *, const char *); int (*commit)(struct dircache_ctx *, const char *); - int (*checkout)(struct dircache_ctx *, const char *); - int (*get_branch)(struct dircache_ctx *, char **); + int (*branch_get)(struct dircache_ctx *, char **); + int (*branch_set)(struct dircache_ctx *, const char *); + int (*workdir_get)(struct dircache_ctx *, char **); + int (*workdir_set)(struct dircache_ctx *, const char *); int (*fsck)(struct dircache_ctx *); int (*compress)(struct dircache_ctx *); int (*dedup)(struct dircache_ctx *); diff --git a/helper.c b/helper.c @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2014 Mohamed Aslan <maslan@sce.carleton.ca> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/stat.h> + +#include "helper.h" +#include "config.h" + +/* TODO: add support for multiple parents */ +struct commit * +baseline_helper_commit_build(struct dircache_ctx *dc_ctx, const char *dir_id, const char *parent_head, const char *msg_file) +{ + char *line = NULL; + const char *user_name, *user_email; + size_t size = 0; + struct stat s; + struct commit *comm; + FILE *mfp; + + comm = baseline_commit_new(); + if ((user_name = baseline_config_get_val("username")) == NULL) + return NULL; + if ((user_email = baseline_config_get_val("useremail")) == NULL) + return NULL; + if (msg_file == NULL) + return NULL; + if (stat(msg_file, &s) == -1) + return NULL; + comm->dir = strdup(dir_id); + comm->author.name = strdup(user_name); + comm->author.email = strdup(user_email); + comm->committer.name = strdup(user_name); + comm->committer.email = strdup(user_email); + if (parent_head != NULL) { + comm->parents[0] = strdup(parent_head); + comm->n_parents = 1; + } + else { + comm->n_parents = 0; + } + /* commit message */ + if ((mfp = fopen(msg_file, "r")) == NULL) + return NULL; + /* FIXME: loading the whole message file in memory */ + if ((comm->message = (char *)malloc(s.st_size)) == NULL) + return NULL; + while (getline(&line, &size, mfp) != -1) + strlcat(comm->message, line, s.st_size); + fclose(mfp); + return comm; +} + diff --git a/helper.h b/helper.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2014 Mohamed Aslan <maslan@sce.carleton.ca> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _HELPER_H_ +#define _HELPER_H_ + +#include "objects.h" +#include "dircache.h" + +struct commit* baseline_helper_commit_build(struct dircache_ctx *, const char *, const char *, const char *); + +#endif diff --git a/objdb-fs.c b/objdb-fs.c @@ -26,6 +26,7 @@ #include <fts.h> /* fts_*(3) */ #include "defaults.h" +#include "objects.h" #include "objdb.h" int objdb_baseline_get_ops(struct objdb_ops **); @@ -33,12 +34,10 @@ static char * get_objdb_dir(struct objdb_ctx *); static int objdb_bl_open(struct objdb_ctx **, const char *, const char *); static int objdb_bl_close(struct objdb_ctx *); static int objdb_bl_init(struct objdb_ctx *); -static int objdb_bl_insert(struct objdb_ctx *, enum objdb_type, const u_int8_t *, char **); -static int objdb_bl_insert_from_file(struct objdb_ctx *, enum objdb_type, const char *, char **); +static int objdb_bl_insert_file(struct objdb_ctx *, struct file *); +static int objdb_bl_insert_dir(struct objdb_ctx *, struct dir *); +static int objdb_bl_insert_commit(struct objdb_ctx *, struct commit *); static int objdb_bl_remove(struct objdb_ctx *, const char *, const char *); -static int objdb_bl_dir_begin(struct objdb_ctx *, struct objdb_dirhandle **); -static int objdb_bl_dir_insert_object(struct objdb_ctx *, struct objdb_dirhandle *, const char *, const char *, enum objdb_type, mode_t); -static int objdb_bl_dir_end(struct objdb_ctx *, struct objdb_dirhandle *, char **); static int objdb_bl_branch_create(struct objdb_ctx *, const char *); static int objdb_bl_branch_create_from(struct objdb_ctx *, const char *, const char *); static int objdb_bl_branch_if_exists(struct objdb_ctx *, const char *, int *); @@ -53,12 +52,10 @@ static const struct objdb_ops baseline_objdb_ops = { .init = objdb_bl_init, .open = objdb_bl_open, .close = objdb_bl_close, - .insert = objdb_bl_insert, - .insert_from_file = objdb_bl_insert_from_file, + .insert_file = objdb_bl_insert_file, + .insert_dir = objdb_bl_insert_dir, + .insert_commit = objdb_bl_insert_commit, .remove = objdb_bl_remove, - .dir_begin = objdb_bl_dir_begin, - .dir_insert_object = objdb_bl_dir_insert_object, - .dir_end = objdb_bl_dir_end, .branch_create = objdb_bl_branch_create, .branch_create_from = objdb_bl_branch_create_from, .branch_if_exists = objdb_bl_branch_if_exists, @@ -155,74 +152,80 @@ ret: } static int -objdb_bl_insert(struct objdb_ctx *ctx, enum objdb_type type, const u_int8_t *data, char **obj_id) +objdb_bl_insert_file(struct objdb_ctx *ctx, struct file *file) { - return EXIT_SUCCESS; -} + char *db_dir_name, *full_path, *obj_file_name, *obj_hash, *tmp_file_name; + char *buf[4096]; + int n, retval, tmpfd; + off_t offset; -static int -objdb_bl_insert_from_file(struct objdb_ctx *ctx, enum objdb_type type, const char *file_name, char **obj_id) -{ - char *db_dir_name, *full_path, *obj_file_name, *obj_hash, *ptr, *tmp_file_name; - int count, i, len, retval, tmpfd; - FILE *fp, *tmpfp; - SHA2_CTX hash_ctx; - struct stat s; - u_int8_t buf[4096], digest[SHA256_DIGEST_LENGTH]; - - if (file_name == NULL) { - retval = EXIT_FAILURE; - goto ret; - } - if ((fp = fopen(file_name, "r")) == NULL) { - retval = EXIT_FAILURE; - goto ret; - } db_dir_name = get_objdb_dir(ctx); if (db_dir_name == NULL) { retval = EXIT_FAILURE; goto ret; } - /* check object's type */ - if (type == T_FILE) { - /* malloc() + strlcpy() + strlcat() = asprintf() */ - len = asprintf(&full_path, "%s/%s", db_dir_name, "files"); + asprintf(&full_path, "%s/%s", db_dir_name, "files"); + obj_hash = baseline_gen_id(file, O_FILE); + /* create a temp file */ + asprintf(&tmp_file_name, "%s/tmp.XXXXXX", full_path); + if ((tmpfd = mkstemp(tmp_file_name)) == -1) { + retval = EXIT_FAILURE; + goto ret; } - else if (type == T_DIR) { - len = asprintf(&full_path, "%s/%s", db_dir_name, "dirs"); + if (file->loc == ON_FS) { + /* save file offset */ + offset = lseek(file->fd, 0, SEEK_CUR); + /* copy file content */ + while((n = read(file->fd, buf, sizeof(buf))) > 0) + write(tmpfd, buf, n); + /* restore file offset */ + lseek(file->fd, offset, SEEK_SET); } - else if (type == T_COMMIT) { - len = asprintf(&full_path, "%s/%s", db_dir_name, "commits"); + else if (file->loc == ON_MEM) { + write(tmpfd, file->buffer, strlen(file->buffer)); } - else if (type == T_TAG) { - len = asprintf(&full_path, "%s/%s", db_dir_name, "tags"); + close(tmpfd); + asprintf(&obj_file_name, "%s/%s", full_path, obj_hash); + /* check if file is already there */ + if (access(obj_file_name, F_OK) != -1) { + unlink(tmp_file_name); + goto success; } - else { - len = asprintf(&full_path, "%s", db_dir_name); + if (rename(tmp_file_name, obj_file_name)) { + retval = EXIT_FAILURE; + goto ret; } -#ifdef DEBUG - printf("[DEBUG] DB: checking for path = %s\n", full_path); -#endif - /* check if path exists */ - if (stat(full_path, &s) != 0) { -#ifdef DEBUG - printf("\t[DEBUG] DB: creating new dir %s\n", full_path); -#endif - if (mkdir(full_path, S_IRUSR | S_IWUSR | S_IXUSR) != 0) { - retval = EXIT_FAILURE; - goto ret; - } - } - else { - if (!S_ISDIR(s.st_mode)) { - retval = EXIT_FAILURE; - goto ret; - } +success: + retval = EXIT_SUCCESS; +ret: + /* assuming free(NULL) is safe */ + free(db_dir_name); + free(full_path); + free(obj_file_name); + free(tmp_file_name); + return retval; +} + +static int +objdb_bl_insert_dir(struct objdb_ctx *ctx, struct dir *dir) +{ + char *db_dir_name, *full_path, *obj_file_name, *obj_hash, *tmp_file_name; + char *data; + int retval, tmpfd; + FILE *tmpfp; + + db_dir_name = get_objdb_dir(ctx); + if (db_dir_name == NULL) { + retval = EXIT_FAILURE; + goto ret; } + asprintf(&full_path, "%s/%s", db_dir_name, "dirs"); + data = baseline_dir_serialize(dir); + obj_hash = baseline_gen_id(dir, O_DIR); + /* create a temp file */ - /* malloc() + strlcpy() + strlcat() = asprintf() */ - len = asprintf(&tmp_file_name, "%s/tmp.XXXXXX", full_path); + asprintf(&tmp_file_name, "%s/tmp.XXXXXX", full_path); if ((tmpfd = mkstemp(tmp_file_name)) == -1) { retval = EXIT_FAILURE; goto ret; @@ -233,25 +236,9 @@ objdb_bl_insert_from_file(struct objdb_ctx *ctx, enum objdb_type type, const cha retval = EXIT_FAILURE; goto ret; } - SHA256Init(&hash_ctx); - do { - count = fread(buf, sizeof(u_int8_t), sizeof(buf), fp); - fwrite(buf, sizeof(u_int8_t), count, tmpfp); /* faster for new a file, but slower if the file already exist! */ - SHA256Update(&hash_ctx, buf, count); - } while (!feof(fp)); - SHA256Final(digest, &hash_ctx); - fclose(fp); - fclose(tmpfp); - /* TODO: think of something safer */ - obj_hash = (char *)malloc(SHA256_DIGEST_LENGTH * 2 + 1); - for (i=0, ptr=obj_hash ; i<SHA256_DIGEST_LENGTH ; i++, ptr+=2) { - snprintf(ptr, 3, "%02x", digest[i]); - } - /* malloc() + strlcpy() + strlcat() = asprintf() */ + fwrite(data, sizeof(u_int8_t), strlen(data), tmpfp); + fclose(tmpfp); asprintf(&obj_file_name, "%s/%s", full_path, obj_hash); -#ifdef DEBUG - printf("[DEBUG] DB: object file name = %s\n", obj_file_name); -#endif /* check if file is already there */ if (access(obj_file_name, F_OK) != -1) { unlink(tmp_file_name); @@ -263,7 +250,6 @@ objdb_bl_insert_from_file(struct objdb_ctx *ctx, enum objdb_type type, const cha } success: - *obj_id = obj_hash; retval = EXIT_SUCCESS; ret: /* assuming free(NULL) is safe */ @@ -275,73 +261,65 @@ ret: } static int -objdb_bl_remove(struct objdb_ctx *ctx, const char *group_name, const char *obj_name) +objdb_bl_insert_commit(struct objdb_ctx *ctx, struct commit *comm) { - return EXIT_SUCCESS; -} - -static int -objdb_bl_dir_begin(struct objdb_ctx *ctx, struct objdb_dirhandle **handle) -{ - char *db_dir_name; - char *tmp_file_name; - int len, tmpfd; + char *db_dir_name, *full_path, *obj_file_name, *obj_hash, *tmp_file_name; + char *data; + int retval, tmpfd; FILE *tmpfp; + db_dir_name = get_objdb_dir(ctx); - /* malloc() + strlcpy() + strlcat() = asprintf() */ - len = asprintf(&tmp_file_name, "%s/tmp.XXXXXX", db_dir_name); + if (db_dir_name == NULL) { + retval = EXIT_FAILURE; + goto ret; + } + asprintf(&full_path, "%s/%s", db_dir_name, "commits"); + data = baseline_commit_serialize(comm); + obj_hash = baseline_gen_id(comm, O_COMMIT); + + /* create a temp file */ + asprintf(&tmp_file_name, "%s/tmp.XXXXXX", full_path); if ((tmpfd = mkstemp(tmp_file_name)) == -1) { - return EXIT_FAILURE; + retval = EXIT_FAILURE; + goto ret; } if ((tmpfp = fdopen(tmpfd, "w")) == NULL) { unlink(tmp_file_name); close(tmpfd); - return EXIT_FAILURE; + retval = EXIT_FAILURE; + goto ret; } - *handle = (struct objdb_dirhandle *)malloc(sizeof(struct objdb_dirhandle)); - (*handle)->id = tmpfd; - (*handle)->name = strdup(tmp_file_name); + fwrite(data, sizeof(u_int8_t), strlen(data), tmpfp); + fclose(tmpfp); + asprintf(&obj_file_name, "%s/%s", full_path, obj_hash); + /* check if file is already there */ + if (access(obj_file_name, F_OK) != -1) { + unlink(tmp_file_name); + goto success; + } + if (rename(tmp_file_name, obj_file_name)) { + retval = EXIT_FAILURE; + goto ret; + } + +success: + retval = EXIT_SUCCESS; +ret: + /* assuming free(NULL) is safe */ free(db_dir_name); + free(full_path); + free(obj_file_name); free(tmp_file_name); - return EXIT_SUCCESS; + return retval; } static int -objdb_bl_dir_insert_object(struct objdb_ctx *ctx, struct objdb_dirhandle *handle, const char *objid, const char *name, enum objdb_type type, mode_t mode) +objdb_bl_remove(struct objdb_ctx *ctx, const char *group_name, const char *obj_name) { - char *entry; - int len; - /* TODO: check if obj exists! */ - if (type == T_FILE) { - /* FIXME: non-portable code */ - len = asprintf(&entry, "%c %s %06o %s\n", 'F', objid, mode, name); - /* FIXME: error checking */ - write(handle->id, entry, len); - } - else if (type == T_DIR) { - /* FIXME: non-portable code */ - len = asprintf(&entry, "%c %s %06o %s\n", 'D', objid, mode, name); - /* FIXME: error checking */ - write(handle->id, entry, len); - } return EXIT_SUCCESS; } static int -objdb_bl_dir_end(struct objdb_ctx *ctx, struct objdb_dirhandle *handle, char **objid) -{ - enum objdb_type type = T_DIR; - int retval; - close(handle->id); - retval = objdb_bl_insert_from_file(ctx, type, handle->name, objid); - if (retval == EXIT_SUCCESS) - unlink(handle->name); - free(handle->name); - free(handle); - return retval; -} - -static int objdb_bl_branch_create(struct objdb_ctx *ctx, const char *branch_name) { char *db_dir_name = NULL; diff --git a/objdb.h b/objdb.h @@ -18,18 +18,7 @@ #define _OBJDB_H_ #include <sys/types.h> - -enum objdb_type { - T_FILE, - T_DIR, - T_COMMIT, - T_TAG -}; - -struct objdb_dirhandle { - int id; - char *name; -}; +#include "objects.h" struct objdb_ctx { char *db_name; @@ -44,13 +33,11 @@ struct objdb_ops { int (*open)(struct objdb_ctx **, const char *, const char *); int (*close)(struct objdb_ctx *); int (*init)(struct objdb_ctx *); - /* file ops*/ - int (*insert)(struct objdb_ctx *, enum objdb_type, const u_int8_t *, char **); - int (*insert_from_file)(struct objdb_ctx *, enum objdb_type, const char *, char **); - /* dir ops */ - int (*dir_begin)(struct objdb_ctx *, struct objdb_dirhandle **); - int (*dir_insert_object)(struct objdb_ctx *, struct objdb_dirhandle *, const char *, const char *, enum objdb_type, mode_t); - int (*dir_end)(struct objdb_ctx *, struct objdb_dirhandle *, char **); + /* file ops */ + //int (*insert_from_file)(struct objdb_ctx *, enum objdb_type, const char *, char **); + int (*insert_file)(struct objdb_ctx *, struct file *); + int (*insert_dir)(struct objdb_ctx *, struct dir *); + int (*insert_commit)(struct objdb_ctx *, struct commit *); /* branch ops */ int (*branch_create)(struct objdb_ctx *, const char *); int (*branch_create_from)(struct objdb_ctx *, const char *, const char *); diff --git a/objects.c b/objects.c @@ -0,0 +1,227 @@ +/* + * Copyright (c) 2014 Mohamed Aslan <maslan@sce.carleton.ca> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> /* read(2) */ + +#include <sha2.h> + +#include "objects.h" + +struct file * +baseline_file_new() +{ + struct file *file = (struct file *)calloc(1, sizeof(struct file)); + return file; +} + +void +baseline_file_free(struct file *file) +{ + if (file == NULL) + return; + free(file->id); + if (file->loc == ON_MEM) + free(file->buffer); + free(file); +} + +struct commit * +baseline_commit_new() +{ + struct commit *comm = (struct commit *)calloc(1, sizeof(struct commit)); + return comm; +} + +void +baseline_commit_free(struct commit *comm) +{ + int i; + if (comm == NULL) + return; + free(comm->id); + free(comm->dir); + for (i=0 ; i<comm->n_parents ; i++) + free(comm->parents[i]); + free(comm->message); + 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>\ncommitter %s <%s>\n%s\n", + comm->dir, comm->author.name, comm->author.email, + comm->committer.name, comm->committer.email, comm->message); + else if (comm->n_parents == 1) + asprintf(&raw, "dir %s\nparent %s\nauthor %s <%s>\ncommitter %s <%s>\n%s\n", + comm->dir, comm->parents[0], comm->author.name, comm->author.email, + comm->committer.name, comm->committer.email, comm->message); + /* TODO: support more than 1 parent */ +ret: + return raw; +} + +struct dir * +baseline_dir_new() +{ + struct dir *dir = (struct dir *)calloc(1, sizeof(struct dir)); + dir->children = NULL; + return dir; +} + +void +baseline_dir_free(struct dir *dir) +{ + struct dirent *it, *ptr; + + if (dir == NULL) + return; + if (dir->children == NULL) { + free(dir); + return; + } + for (it = dir->children ; it != NULL ;) { + ptr = it; + it = it->next; + free(ptr); + } + free(dir); +} + +void +baseline_dir_append(struct dir *dir, struct dirent *ent) +{ + struct dirent *it; + + if (dir == NULL || ent == NULL) + return; + if (dir->children == NULL) { + dir->children = ent; + } + else { + for (it = dir->children ; it->next != NULL ; it = it->next); + it->next = 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 @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2014 Mohamed Aslan <maslan@sce.carleton.ca> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _OBJECTS_H_ +#define _OBJECTS_H_ + +#include <fcntl.h> + +#define MAX_PARENTS 1 + +enum objtype { + O_FILE, + O_DIR, + O_COMMIT, + O_TAG +}; + +struct user { + char *name; + char *email; +}; + +struct commit { + char *id; /* do we really need that? */ + char *dir; + struct user author; + struct user committer; + u_int8_t n_parents; + char *parents[MAX_PARENTS]; + char *message; +}; + +struct dirent { + char *id; + char *name; + enum { + T_FILE, + T_DIR + } type; + mode_t mode; + struct dirent *next; +}; + +struct dir { + char *id; + struct dir *parent; /* currently unused */ + struct dirent *children; +}; + +struct file { + char *id; + enum { + ON_FS, + ON_MEM + } loc; + union { + int fd; + char *buffer; + }; +}; + +/* file ops */ +struct file* baseline_file_new(); +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 diff --git a/session.c b/session.c @@ -46,7 +46,7 @@ baseline_session_begin(struct session *s, u_int8_t options) s->repo_baselinedir = baseline_repo_get_baselinedir(); if (s->repo_rootdir == NULL) - errx(EXIT_FAILURE, "error, no repository is found."); + errx(EXIT_FAILURE, "error, no repository was found."); if (s->db_ops->open(&(s->db_ctx), BASELINE_DB, s->repo_baselinedir) == EXIT_FAILURE) return EXIT_FAILURE; if (s->dc_ops->open(&(s->dc_ctx), s->db_ctx, s->db_ops, s->repo_rootdir, s->repo_baselinedir) == EXIT_FAILURE) @@ -59,7 +59,7 @@ baseline_session_begin(struct session *s, u_int8_t options) free(config); /* get current branch */ - s->dc_ops->get_branch(s->dc_ctx, (char **)&(s->branch)); + s->dc_ops->branch_get(s->dc_ctx, (char **)&(s->branch)); return EXIT_SUCCESS; } diff --git a/session.h b/session.h @@ -17,6 +17,8 @@ #ifndef _SESSION_H_ #define _SESSION_H_ +#include <limits.h> + #include "objdb.h" #include "dircache.h" #include "common.h"