baseline

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

commit f3885ee60daed0edd4006cac44bdbe170e8b7957
parent 1a5a06dfaa6278f25192d9892c66da011f6fdf97
Author: Mohamed Aslan <maslan@sce.carleton.ca>
Date:   Mon, 26 May 2014 13:34:31 -0400

removed all hard-coded paths and fixed baseline commands from inside repository sub-dirs

Diffstat:
Mcmd-add.c | 26++++++++++++++++----------
Mcmd-commit.c | 38+++++++++++++++++++-------------------
Mcmd-init.c | 2+-
Mdefaults.h | 1+
Mdircache-simple.c | 156++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------
Mdircache.h | 5+++--
Mobjdb-fs.c | 5+++--
Msession.c | 2+-
8 files changed, 175 insertions(+), 60 deletions(-)

diff --git a/cmd-add.c b/cmd-add.c @@ -24,21 +24,25 @@ #include "session.h" #include "cmd.h" + +static char * +xrealpath(const char *path) +{ + char abspath[PATH_MAX+1]; + if (realpath(path, abspath) == NULL) + errx(EXIT_FAILURE, "error, failed to resolve path."); + return strdup(abspath); +} + /* * checks if first is subdir of second */ static int is_subdir_of(const char *first, const char *second) { - char first_abspath[PATH_MAX+1]; if (first == NULL || second == NULL) return 0; - if (realpath(first, first_abspath) == NULL) - return 0; -#ifdef DEBUG - printf("DEBUG: realpath: %s\n", first_abspath); -#endif - if (strstr(first_abspath, second) == first_abspath) + if (strstr(first, second) == first) return 1; return 0; } @@ -46,7 +50,7 @@ is_subdir_of(const char *first, const char *second) int cmd_add(int argc, char **argv) { - char *path; + char *path, *real; struct session s; struct stat st; @@ -55,11 +59,13 @@ cmd_add(int argc, char **argv) path = argv[1]; if (path == NULL) errx(EXIT_FAILURE, "error, no path specified."); - if (!is_subdir_of(path, s.repo_rootdir)) + /* all paths send to the backends must be non-relative paths */ + real = xrealpath(path); + if (!is_subdir_of(real, s.repo_rootdir)) errx(EXIT_FAILURE, "error, can not add files from outside the repository."); if (stat(path, &st) == -1) errx(EXIT_FAILURE, "error, \'%s\' does not exist.", path); - if (s.dc_ops->insert(s.dc_ctx, path) == EXIT_FAILURE) + if (s.dc_ops->insert(s.dc_ctx, real) == EXIT_FAILURE) errx(EXIT_FAILURE, "failed to add \'%s\'.", path); baseline_session_end(&s); diff --git a/cmd-commit.c b/cmd-commit.c @@ -33,16 +33,15 @@ static const char msg_head[] = { "# Lines starting with \'#\' will be ignored.\n" }; -int -gen_temp_msgfile_from_msg(char **filename, const char *msg) +static int +gen_temp_msgfile_from_msg(const char *path, char **filename, const char *msg) { char *msg_file = NULL; int msgfd; if (msg == NULL) return EXIT_FAILURE; - /* FIXME: get baseline dir */ - asprintf(&msg_file, "%s/tmp.XXXXXX", BASELINE_DIR); + asprintf(&msg_file, "%s/tmp.XXXXXX", path); if ((msgfd = mkstemp(msg_file)) == -1) return EXIT_FAILURE; if (write(msgfd, msg, strlen(msg)) == -1) @@ -54,13 +53,13 @@ gen_temp_msgfile_from_msg(char **filename, const char *msg) return EXIT_SUCCESS; } -int -gen_temp_msgfile(char **filename) +static int +gen_temp_msgfile(const char *path, char **filename) { char *msg_file = NULL; int msgfd; - /* FIXME: get baseline dir */ - asprintf(&msg_file, "%s/tmp.XXXXXX", BASELINE_DIR); + + asprintf(&msg_file, "%s/tmp.XXXXXX", path); if ((msgfd = mkstemp(msg_file)) == -1) return EXIT_FAILURE; if (write(msgfd, msg_head, sizeof(msg_head) - 1) == -1) @@ -69,16 +68,17 @@ gen_temp_msgfile(char **filename) *filename = msg_file; return EXIT_SUCCESS; } -int -process_msgfile(char **filename) + +static int +process_msgfile(const char *path, char **filename) { char *proc_file = NULL; char *line = NULL; int pfd; size_t size = 0; FILE *fp; - /* FIXME: get baseline dir */ - asprintf(&proc_file, "%s/tmp.XXXXXX", BASELINE_DIR); + + asprintf(&proc_file, "%s/tmp.XXXXXX", path); if ((pfd = mkstemp(proc_file)) == -1) return EXIT_FAILURE; if((fp = fopen(*filename, "r")) == NULL) { @@ -106,7 +106,7 @@ failure: int cmd_commit(int argc, char **argv) { - char *commit_msg, *msg_file; + char *commit_msg = NULL, *msg_file; char *exec; const char *editor; int ch; @@ -135,13 +135,13 @@ cmd_commit(int argc, char **argv) } if (flag_msg) { /* TODO: should be per-stage file */ - if (gen_temp_msgfile_from_msg(&msg_file, commit_msg) == EXIT_FAILURE) - errx(EXIT_FAILURE, "failed to generate commit message"); + if (gen_temp_msgfile_from_msg(s.repo_baselinedir, &msg_file, commit_msg) == EXIT_FAILURE) + errx(EXIT_FAILURE, "error, failed to generate commit message"); free(commit_msg); } else { - if (gen_temp_msgfile(&msg_file) == EXIT_FAILURE) - errx(EXIT_FAILURE, "failed to generate commit message"); + if (gen_temp_msgfile(s.repo_baselinedir, &msg_file) == EXIT_FAILURE) + errx(EXIT_FAILURE, "error, failed to generate commit message"); if((editor = baseline_config_get_val("editor")) != NULL && strcmp(editor, "")) { asprintf(&exec, "%s %s", editor, msg_file); system(exec); @@ -156,8 +156,8 @@ cmd_commit(int argc, char **argv) errx(EXIT_FAILURE, "error, commit message not specified."); } } - if (process_msgfile(&msg_file) == EXIT_FAILURE) - errx(EXIT_FAILURE, "failed to process commit message"); + if (process_msgfile(s.repo_baselinedir, &msg_file) == EXIT_FAILURE) + errx(EXIT_FAILURE, "error, failed to process commit message"); if (s.dc_ops->commit(s.dc_ctx, msg_file) == EXIT_FAILURE) fprintf(stderr, "baseline: error, failed to commit your changes.\n"); diff --git a/cmd-init.c b/cmd-init.c @@ -51,7 +51,7 @@ init(struct session *s) { s->db_ops->open(&(s->db_ctx), BASELINE_DB, baseline_path); s->db_ops->init(s->db_ctx); /* as well as dircache */ - s->dc_ops->open(&(s->dc_ctx), s->db_ctx, s->db_ops, baseline_path); + s->dc_ops->open(&(s->dc_ctx), s->db_ctx, s->db_ops, s->cwd, baseline_path); s->dc_ops->init(s->dc_ctx); free(config_path); diff --git a/defaults.h b/defaults.h @@ -20,6 +20,7 @@ #define BASELINE_DIR ".baseline" #define BASELINE_DB "db" #define BASELINE_CONFIGFILE "config" +#define BASELINE_DIRCACHE "dircache" #define DEFAULT_BRANCH "master" #endif diff --git a/dircache-simple.c b/dircache-simple.c @@ -29,7 +29,7 @@ #include "dircache.h" int dircache_simple_get_ops(struct dircache_ops **); -static int simple_open(struct dircache_ctx **, struct objdb_ctx *, struct objdb_ops *, const char *); +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 *); @@ -63,15 +63,98 @@ dircache_simple_get_ops(struct dircache_ops **ops) return EXIT_SUCCESS; } +/* FIXME */ +static char * +get_dircache_path(struct dircache_ctx *ctx) +{ + char *path = NULL; + + if (ctx == NULL) + return NULL; + asprintf(&path, "%s/%s", ctx->repo_baselinepath, BASELINE_DIRCACHE); + return path; +} + +static const char * +strmismatch(const char *first, const char *second) +{ + int i; + size_t minlen; + + minlen = strlen(first) < strlen(second) ? strlen(first) : strlen(second); + for (i=0 ; i<minlen ; i++) { + if (first[i] == second[i]) + continue; + break; + } +#ifdef DEUG + printf("[DEBUG] mismatch at i = %d\n", i); +#endif + return &first[i]; +} + +static const char* +dir_diff(const char *first, const char *second) +{ + const char *mis = strmismatch(first, second); + if (*mis == '/') + mis++; + return mis; +} + +static int +mkdirp(const char *parent, const char *dir) +{ + char *o, *start, *end; + char *path; + int retval; + struct stat s; + + o = start = end = strdup(dir); + if (*o == '/') { + start++; + end++; + } + while (1) { + if (*end == '\0') + break; + if (*end == '/') { + *end = '\0'; + /* OpenBSD's asprintf(3) uses realloc(), hence no need to free */ + asprintf(&path, "%s/%s", parent, start); +#ifdef DEBUG + printf("[DEBUG] create %s\n", path); +#endif + if (stat(path, &s) == 0) { + if (!S_ISDIR(s.st_mode)) { + retval = EXIT_FAILURE; + goto ret; + } + } + else { + if (mkdir(path, S_IRUSR | S_IWUSR | S_IXUSR) == -1) + return EXIT_FAILURE; + } + *end = '/'; + } + end++; + } +ret: + free(path); + free(o); + return EXIT_SUCCESS; +} + static int -simple_open(struct dircache_ctx **dc_ctx, struct objdb_ctx *db_ctx, struct objdb_ops *db_ops, const char *path) +simple_open(struct dircache_ctx **dc_ctx, struct objdb_ctx *db_ctx, struct objdb_ops *db_ops, const char *rootpath, const char *baselinepath) { if (dc_ctx == NULL || db_ctx == NULL) return EXIT_FAILURE; *dc_ctx = (struct dircache_ctx *)malloc(sizeof(struct dircache_ctx)); (*dc_ctx)->db_ctx = db_ctx; (*dc_ctx)->db_ops = db_ops; - asprintf(&((*dc_ctx)->dc_path), "%s", path); + (*dc_ctx)->repo_rootpath = strdup(rootpath); + (*dc_ctx)->repo_baselinepath = strdup(baselinepath); return EXIT_SUCCESS; } @@ -94,8 +177,8 @@ simple_init(struct dircache_ctx *dc_ctx) if (dc_ctx == NULL) return EXIT_FAILURE; - asprintf(&dc_path, "%s/%s", dc_ctx->dc_path, "dircache"); - asprintf(&branch_path, "%s/branch", dc_ctx->dc_path); + dc_path = get_dircache_path(dc_ctx); + asprintf(&branch_path, "%s/branch", dc_ctx->repo_baselinepath); /* check if '.baseline/dircache' dir exists */ if (stat(dc_path, &s) == -1) { /* create '.baseline/dircache' dir */ @@ -144,10 +227,13 @@ static int simple_insert(struct dircache_ctx *dc_ctx, const char *path) { char *objid, *paths[2], *cache_path; + char *dc_path; struct stat s, fs; FILE *fp; FTS *dir; FTSENT *entry; + + dc_path = get_dircache_path(dc_ctx); if (stat(path, &s) == -1) return EXIT_FAILURE; if (S_ISDIR(s.st_mode)) { @@ -167,7 +253,7 @@ simple_insert(struct dircache_ctx *dc_ctx, const char *path) printf("DS: %s\n", entry->fts_path); #endif /* FIXME: path check is required */ - asprintf(&cache_path, ".baseline/dircache/%s", entry->fts_path); + asprintf(&cache_path, "%s/%s", dc_path, entry->fts_path); if (mkdir(cache_path, S_IRUSR | S_IWUSR | S_IXUSR) != 0) { free(cache_path); return EXIT_FAILURE; @@ -189,7 +275,7 @@ simple_insert(struct dircache_ctx *dc_ctx, const char *path) printf("\t ID = %s\n", objid); #endif /* FIXME: path check is required */ - asprintf(&cache_path, ".baseline/dircache/%s", entry->fts_path); + asprintf(&cache_path, "%s/%s", dc_path, entry->fts_path); if ((fp = fopen(cache_path, "w")) == NULL) { free(cache_path); return EXIT_FAILURE; @@ -206,13 +292,27 @@ simple_insert(struct dircache_ctx *dc_ctx, const char *path) } else { /* it's a file, why the hell would we wait, insert it immediately */ - return dc_ctx->db_ops->insert_from_file(dc_ctx->db_ctx, T_FILE, path, &objid); + 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) + return EXIT_FAILURE; + 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)); + printf("now create %s\n", cache_path); + if ((fp = fopen(cache_path, "w")) == NULL) { + free(cache_path); + return EXIT_FAILURE; + } + fprintf(fp, "F %s %06o\n", objid, fs.st_mode); + fclose(fp); + free(cache_path); } return EXIT_SUCCESS; } static int -simple_gen_dindex(char **didx) +simple_gen_dindex(struct dircache_ctx *dc_ctx, char **didx) { char *dircache_path, *didx_path = NULL; char *paths[2]; @@ -221,14 +321,14 @@ simple_gen_dindex(char **didx) FILE *didx_fp; FTS *ftsp; FTSENT *entry; - /* FIXME: root dir */ - asprintf(&dircache_path, ".baseline/dircache"); + + dircache_path = get_dircache_path(dc_ctx); if (stat(dircache_path, &s) == -1) return EXIT_FAILURE; if (!S_ISDIR(s.st_mode)) return EXIT_FAILURE; /* create dir-only index */ - asprintf(&didx_path, ".baseline/dindex.XXXXXXX"); + asprintf(&didx_path, "%s/dindex.XXXXXXX", dc_ctx->repo_baselinepath); if ((didx_fd = mkstemp(didx_path)) == -1) { return EXIT_FAILURE; } @@ -260,9 +360,9 @@ simple_gen_dindex(char **didx) } static int -simple_gen_commit(const char *dir_id, const char *msg_file, char **commit_file) +simple_gen_commit(struct dircache_ctx *dc_ctx, const char *dir_id, const char *msg_file, char **commit_file) { - char *dc_path = ".baseline/dircache"; /* FIXME */ + char *dc_path; char *cmt_path; char *msg = NULL; const char *user_name, *user_email; @@ -271,6 +371,7 @@ simple_gen_commit(const char *dir_id, const char *msg_file, char **commit_file) 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) @@ -303,17 +404,19 @@ simple_gen_commit(const char *dir_id, const char *msg_file, char **commit_file) fclose(cfp); fclose(mfp); *commit_file = cmt_path; - return EXIT_SUCCESS; + 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; - /* FIXME: */ + + asprintf(&branch_fname, "%s/branch", dc_ctx->repo_baselinepath); *branch_name = NULL; - if ((branch_fp = fopen(".baseline/branch", "r")) == NULL) { + if ((branch_fp = fopen(branch_fname, "r")) == NULL) { return EXIT_FAILURE; } if (getline(branch_name, &size, branch_fp) == -1) { @@ -321,6 +424,7 @@ simple_get_branch(struct dircache_ctx *dc_ctx, char **branch_name) return EXIT_FAILURE; } fclose(branch_fp); + free(branch_fname); return EXIT_SUCCESS; } @@ -340,14 +444,13 @@ simple_commit(struct dircache_ctx *dc_ctx, const char *msgfile) ssize_t len; char type; - /* FIXME: root dir */ - asprintf(&dircache_path, ".baseline/dircache"); + dircache_path = get_dircache_path(dc_ctx); if (stat(dircache_path, &s) == -1) return EXIT_FAILURE; if (!S_ISDIR(s.st_mode)) return EXIT_FAILURE; /* FIXME: empty dirache directory */ - simple_gen_dindex(&didx_path); + simple_gen_dindex(dc_ctx, &didx_path); if ((didx_fp = fopen(didx_path, "r")) == NULL) return EXIT_FAILURE; size = 0; @@ -411,12 +514,12 @@ simple_commit(struct dircache_ctx *dc_ctx, const char *msgfile) fclose(didx_fp); unlink(didx_path); /* temp */ - unlink(".baseline/dircache"); - if (mkdir(".baseline/dircache", S_IRUSR | S_IWUSR | S_IXUSR) == -1) { + unlink(dircache_path); + if (mkdir(dircache_path, S_IRUSR | S_IWUSR | S_IXUSR) == -1) { return EXIT_FAILURE; } /* create commit */ - if (simple_gen_commit(objid, msgfile, &path) == EXIT_FAILURE) + if (simple_gen_commit(dc_ctx, objid, 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) return EXIT_FAILURE; @@ -432,14 +535,17 @@ simple_commit(struct dircache_ctx *dc_ctx, const char *msgfile) static int simple_checkout(struct dircache_ctx *dc_ctx, const char *branch_name) { + char *branch_fname; FILE *branch_fp; - /* FIXME: */ - if ((branch_fp = fopen(".baseline/branch", "w")) == NULL) { + + asprintf(&branch_fname, "%s/branch", dc_ctx->repo_baselinepath); + if ((branch_fp = fopen(branch_fname, "w")) == NULL) { return EXIT_FAILURE; } fprintf(branch_fp, branch_name); fclose(branch_fp); /* TODO: copy head files into working dir */ + free(branch_fname); return EXIT_SUCCESS; } diff --git a/dircache.h b/dircache.h @@ -21,7 +21,8 @@ #include "objdb.h" struct dircache_ctx { - char *dc_path; + char *repo_rootpath; + char *repo_baselinepath; struct objdb_ctx *db_ctx; struct objdb_ops *db_ops; }; @@ -29,7 +30,7 @@ struct dircache_ctx { struct dircache_ops { char *name; char *version; - int (*open)(struct dircache_ctx **, struct objdb_ctx *, struct objdb_ops *, const char *); + int (*open)(struct dircache_ctx **, struct objdb_ctx *, struct objdb_ops *, const char *, const char *); int (*close)(struct dircache_ctx *); int (*init)(struct dircache_ctx *); int (*insert)(struct dircache_ctx *, const char *); diff --git a/objdb-fs.c b/objdb-fs.c @@ -141,7 +141,6 @@ objdb_bl_init(struct objdb_ctx *ctx) asprintf(&maindir, "%s/%s", db_dir_name, main_dirs[i]); if (mkdir(maindir, S_IRUSR | S_IWUSR | S_IXUSR) != 0) { free(maindir); - printf("HERE\n"); goto ret; } free(maindir); @@ -299,7 +298,7 @@ objdb_bl_dir_begin(struct objdb_ctx *ctx, struct objdb_dirhandle **handle) } *handle = (struct objdb_dirhandle *)malloc(sizeof(struct objdb_dirhandle)); (*handle)->id = tmpfd; - asprintf(&((*handle)->name), "%s", tmp_file_name); + (*handle)->name = strdup(tmp_file_name); free(db_dir_name); free(tmp_file_name); return EXIT_SUCCESS; @@ -314,11 +313,13 @@ objdb_bl_dir_insert_object(struct objdb_ctx *ctx, struct objdb_dirhandle *handle 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; diff --git a/session.c b/session.c @@ -49,7 +49,7 @@ baseline_session_begin(struct session *s, u_int8_t options) errx(EXIT_FAILURE, "error, no repository is 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_baselinedir) == EXIT_FAILURE) + if (s->dc_ops->open(&(s->dc_ctx), s->db_ctx, s->db_ops, s->repo_rootdir, s->repo_baselinedir) == EXIT_FAILURE) return EXIT_FAILURE; /* load configurations */