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:
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 */