Ejemplo n.º 1
0
static int loose_backend__foreach(git_odb_backend *_backend, git_odb_foreach_cb cb, void *data)
{
	char *objects_dir;
	int error;
	git_buf buf = GIT_BUF_INIT;
	struct foreach_state state;
	loose_backend *backend = (loose_backend *) _backend;

	assert(backend && cb);

	objects_dir = backend->objects_dir;

	git_buf_sets(&buf, objects_dir);
	git_path_to_dir(&buf);
	if (git_buf_oom(&buf))
		return -1;

	memset(&state, 0, sizeof(state));
	state.cb = cb;
	state.data = data;
	state.dir_len = git_buf_len(&buf);

	error = git_path_direach(&buf, 0, foreach_cb, &state);

	git_buf_dispose(&buf);

	return error;
}
Ejemplo n.º 2
0
int git_path_find_dir(git_buf *dir, const char *path, const char *base)
{
	int error = GIT_SUCCESS;

	if (base != NULL && git_path_root(path) < 0)
		error = git_buf_joinpath(dir, base, path);
	else
		error = git_buf_sets(dir, path);

	if (error == GIT_SUCCESS) {
		char buf[GIT_PATH_MAX];
		if (p_realpath(dir->ptr, buf) != NULL)
			error = git_buf_sets(dir, buf);
	}

	/* call dirname if this is not a directory */
	if (error == GIT_SUCCESS && git_path_isdir(dir->ptr) != GIT_SUCCESS)
		if (git_path_dirname_r(dir, dir->ptr) < GIT_SUCCESS)
			error = git_buf_lasterror(dir);

	if (error == GIT_SUCCESS)
		error = git_path_to_dir(dir);

	return error;
}
Ejemplo n.º 3
0
const char *cl_git_sandbox_path(int is_dir, ...)
{
	const char *path = NULL;
	static char _temp[GIT_PATH_MAX];
	git_buf buf = GIT_BUF_INIT;
	va_list arg;

	cl_git_pass(git_buf_sets(&buf, clar_sandbox_path()));

	va_start(arg, is_dir);

	while ((path = va_arg(arg, const char *)) != NULL) {
		cl_git_pass(git_buf_joinpath(&buf, buf.ptr, path));
	}
	va_end(arg);

	cl_git_pass(git_path_prettify(&buf, buf.ptr, NULL));
	if (is_dir)
		git_path_to_dir(&buf);

	/* make sure we won't truncate */
	cl_assert(git_buf_len(&buf) < sizeof(_temp));
	git_buf_copy_cstr(_temp, sizeof(_temp), &buf);

	git_buf_dispose(&buf);

	return _temp;
}
Ejemplo n.º 4
0
static int load_workdir(git_repository *repo, git_config *config, git_buf *parent_path)
{
	int         error;
	const git_config_entry *ce;
	git_buf     worktree = GIT_BUF_INIT;

	if (repo->is_bare)
		return 0;

	if ((error = git_config__lookup_entry(
			&ce, config, "core.worktree", false)) < 0)
		return error;

	if (ce && ce->value) {
		if ((error = git_path_prettify_dir(
				&worktree, ce->value, repo->path_repository)) < 0)
			return error;

		repo->workdir = git_buf_detach(&worktree);
	}
	else if (parent_path && git_path_isdir(parent_path->ptr))
		repo->workdir = git_buf_detach(parent_path);
	else {
		if (git_path_dirname_r(&worktree, repo->path_repository) < 0 ||
			git_path_to_dir(&worktree) < 0)
			return -1;

		repo->workdir = git_buf_detach(&worktree);
	}

	GITERR_CHECK_ALLOC(repo->workdir);
	return 0;
}
Ejemplo n.º 5
0
static int load_workdir(git_repository *repo, git_buf *parent_path)
{
	int         error;
	git_config *config;
	const char *worktree;
	git_buf     worktree_buf = GIT_BUF_INIT;

	if (repo->is_bare)
		return 0;

	if (git_repository_config__weakptr(&config, repo) < 0)
		return -1;

	error = git_config_get_string(&worktree, config, "core.worktree");
	if (!error && worktree != NULL)
		repo->workdir = git__strdup(worktree);
	else if (error != GIT_ENOTFOUND)
		return error;
	else {
		giterr_clear();

		if (parent_path && git_path_isdir(parent_path->ptr))
			repo->workdir = git_buf_detach(parent_path);
		else {
			git_path_dirname_r(&worktree_buf, repo->path_repository);
			git_path_to_dir(&worktree_buf);
			repo->workdir = git_buf_detach(&worktree_buf);
		}
	}

	GITERR_CHECK_ALLOC(repo->workdir);

	return 0;
}
Ejemplo n.º 6
0
int git_path_prettify_dir(git_buf *path_out, const char *path, const char *base)
{
	int error = git_path_prettify(path_out, path, base);

	if (error == GIT_SUCCESS)
		error = git_path_to_dir(path_out);

	return error;
}
Ejemplo n.º 7
0
int git_path_direach(
	git_buf *path,
	int (*fn)(void *, git_buf *),
	void *arg)
{
	ssize_t wd_len;
	DIR *dir;
	struct dirent *de, *de_buf;

	if (git_path_to_dir(path) < 0)
		return -1;

	wd_len = git_buf_len(path);

	if ((dir = opendir(path->ptr)) == NULL) {
		giterr_set(GITERR_OS, "Failed to open directory '%s'", path->ptr);
		return -1;
	}

#ifdef __sun
	de_buf = git__malloc(sizeof(struct dirent) + FILENAME_MAX + 1);
#else
	de_buf = git__malloc(sizeof(struct dirent));
#endif

	while (p_readdir_r(dir, de_buf, &de) == 0 && de != NULL) {
		int result;

		if (is_dot_or_dotdot(de->d_name))
			continue;

		if (git_buf_puts(path, de->d_name) < 0) {
			closedir(dir);
			git__free(de_buf);
			return -1;
		}

		result = fn(arg, path);

		git_buf_truncate(path, wd_len); /* restore path */

		if (result < 0) {
			closedir(dir);
			git__free(de_buf);
			return -1;
		}
	}

	closedir(dir);
	git__free(de_buf);
	return 0;
}
Ejemplo n.º 8
0
static void
check_path_to_dir(
	const char* path,
    const char* expected)
{
	git_buf tgt = GIT_BUF_INIT;

	git_buf_sets(&tgt, path);
	cl_git_pass(git_path_to_dir(&tgt));
	cl_assert_equal_s(expected, tgt.ptr);

	git_buf_dispose(&tgt);
}
Ejemplo n.º 9
0
int git_path_find_dir(git_buf *dir, const char *path, const char *base)
{
	int error = git_path_join_unrooted(dir, path, base, NULL);

	if (!error) {
		char buf[GIT_PATH_MAX];
		if (p_realpath(dir->ptr, buf) != NULL)
			error = git_buf_sets(dir, buf);
	}

	/* call dirname if this is not a directory */
	if (!error) /* && git_path_isdir(dir->ptr) == false) */
		error = (git_path_dirname_r(dir, dir->ptr) < 0) ? -1 : 0;

	if (!error)
		error = git_path_to_dir(dir);

	return error;
}
Ejemplo n.º 10
0
static int object_file_name(
	git_buf *name, const loose_backend *be, const git_oid *id)
{
	size_t alloclen;

	/* expand length for object root + 40 hex sha1 chars + 2 * '/' + '\0' */
	GITERR_CHECK_ALLOC_ADD(&alloclen, be->objects_dirlen, GIT_OID_HEXSZ);
	GITERR_CHECK_ALLOC_ADD(&alloclen, alloclen, 3);
	if (git_buf_grow(name, alloclen) < 0)
		return -1;

	git_buf_set(name, be->objects_dir, be->objects_dirlen);
	git_path_to_dir(name);

	/* loose object filename: aa/aaa... (41 bytes) */
	git_oid_pathfmt(name->ptr + name->size, id);
	name->size += GIT_OID_HEXSZ + 1;
	name->ptr[name->size] = '\0';

	return 0;
}
Ejemplo n.º 11
0
int git_path_direach(
	git_buf *path,
	int (*fn)(void *, git_buf *),
	void *arg)
{
	ssize_t wd_len;
	DIR *dir;
	struct dirent *de;

	if (git_path_to_dir(path) < GIT_SUCCESS)
		return git_buf_lasterror(path);

	wd_len = path->size;
	dir = opendir(path->ptr);
	if (!dir)
		return git__throw(GIT_EOSERR, "Failed to process `%s` tree structure. An error occured while opening the directory", path->ptr);

	while ((de = readdir(dir)) != NULL) {
		int result;

		if (is_dot_or_dotdot(de->d_name))
			continue;

		if (git_buf_puts(path, de->d_name) < GIT_SUCCESS)
			return git_buf_lasterror(path);

		result = fn(arg, path);

		git_buf_truncate(path, wd_len); /* restore path */

		if (result != GIT_SUCCESS) {
			closedir(dir);
			return result;	/* The callee is reponsible for setting the correct error message */
		}
	}

	closedir(dir);
	return GIT_SUCCESS;
}
Ejemplo n.º 12
0
int git_path_prettify_dir(git_buf *path_out, const char *path, const char *base)
{
	int error = git_path_prettify(path_out, path, base);
	return (error < 0) ? error : git_path_to_dir(path_out);
}
Ejemplo n.º 13
0
int git_path_direach(
	git_buf *path,
	uint32_t flags,
	int (*fn)(void *, git_buf *),
	void *arg)
{
	int error = 0;
	ssize_t wd_len;
	DIR *dir;
	struct dirent *de;

#ifdef GIT_USE_ICONV
	git_path_iconv_t ic = GIT_PATH_ICONV_INIT;
#endif

	GIT_UNUSED(flags);

	if (git_path_to_dir(path) < 0)
		return -1;

	wd_len = git_buf_len(path);

	if ((dir = opendir(path->ptr)) == NULL) {
		giterr_set(GITERR_OS, "Failed to open directory '%s'", path->ptr);
		if (errno == ENOENT)
			return GIT_ENOTFOUND;

		return -1;
	}

#ifdef GIT_USE_ICONV
	if ((flags & GIT_PATH_DIR_PRECOMPOSE_UNICODE) != 0)
		(void)git_path_iconv_init_precompose(&ic);
#endif

	while ((de = readdir(dir)) != NULL) {
		char *de_path = de->d_name;
		size_t de_len = strlen(de_path);

		if (git_path_is_dot_or_dotdot(de_path))
			continue;

#ifdef GIT_USE_ICONV
		if ((error = git_path_iconv(&ic, &de_path, &de_len)) < 0)
			break;
#endif

		if ((error = git_buf_put(path, de_path, de_len)) < 0)
			break;

		giterr_clear();
		error = fn(arg, path);

		git_buf_truncate(path, wd_len); /* restore path */

		/* Only set our own error if the callback did not set one already */
		if (error != 0) {
			if (!giterr_last())
				giterr_set_after_callback(error);

			break;
		}
	}

	closedir(dir);

#ifdef GIT_USE_ICONV
	git_path_iconv_clear(&ic);
#endif

	return error;
}
Ejemplo n.º 14
0
/* Locate an object matching a given short oid */
static int locate_object_short_oid(
	git_buf *object_location,
	git_oid *res_oid,
	loose_backend *backend,
	const git_oid *short_oid,
	size_t len)
{
	char *objects_dir = backend->objects_dir;
	size_t dir_len = strlen(objects_dir), alloc_len;
	loose_locate_object_state state;
	int error;

	/* prealloc memory for OBJ_DIR/xx/xx..38x..xx */
	GITERR_CHECK_ALLOC_ADD(&alloc_len, dir_len, GIT_OID_HEXSZ);
	GITERR_CHECK_ALLOC_ADD(&alloc_len, alloc_len, 3);
	if (git_buf_grow(object_location, alloc_len) < 0)
		return -1;

	git_buf_set(object_location, objects_dir, dir_len);
	git_path_to_dir(object_location);

	/* save adjusted position at end of dir so it can be restored later */
	dir_len = git_buf_len(object_location);

	/* Convert raw oid to hex formatted oid */
	git_oid_fmt((char *)state.short_oid, short_oid);

	/* Explore OBJ_DIR/xx/ where xx is the beginning of hex formatted short oid */
	if (git_buf_put(object_location, (char *)state.short_oid, 3) < 0)
		return -1;
	object_location->ptr[object_location->size - 1] = '/';

	/* Check that directory exists */
	if (git_path_isdir(object_location->ptr) == false)
		return git_odb__error_notfound("no matching loose object for prefix",
			short_oid, len);

	state.dir_len = git_buf_len(object_location);
	state.short_oid_len = len;
	state.found = 0;

	/* Explore directory to find a unique object matching short_oid */
	error = git_path_direach(
		object_location, 0, fn_locate_object_short_oid, &state);
	if (error < 0 && error != GIT_EAMBIGUOUS)
		return error;

	if (!state.found)
		return git_odb__error_notfound("no matching loose object for prefix",
			short_oid, len);

	if (state.found > 1)
		return git_odb__error_ambiguous("multiple matches in loose objects");

	/* Convert obtained hex formatted oid to raw */
	error = git_oid_fromstr(res_oid, (char *)state.res_oid);
	if (error)
		return error;

	/* Update the location according to the oid obtained */
	GITERR_CHECK_ALLOC_ADD(&alloc_len, dir_len, GIT_OID_HEXSZ);
	GITERR_CHECK_ALLOC_ADD(&alloc_len, alloc_len, 2);

	git_buf_truncate(object_location, dir_len);
	if (git_buf_grow(object_location, alloc_len) < 0)
		return -1;

	git_oid_pathfmt(object_location->ptr + dir_len, res_oid);

	object_location->size += GIT_OID_HEXSZ + 1;
	object_location->ptr[object_location->size] = '\0';

	return 0;
}
Ejemplo n.º 15
0
static int find_repo(
	git_buf *repo_path,
	git_buf *parent_path,
	const char *start_path,
	uint32_t flags,
	const char *ceiling_dirs)
{
	int error;
	git_buf path = GIT_BUF_INIT;
	struct stat st;
	dev_t initial_device = 0;
	bool try_with_dot_git = ((flags & GIT_REPOSITORY_OPEN_BARE) != 0);
	int ceiling_offset;

	git_buf_free(repo_path);

	if ((error = git_path_prettify(&path, start_path, NULL)) < 0)
		return error;

	ceiling_offset = find_ceiling_dir_offset(path.ptr, ceiling_dirs);

	if (!try_with_dot_git &&
		(error = git_buf_joinpath(&path, path.ptr, DOT_GIT)) < 0)
		return error;

	while (!error && !git_buf_len(repo_path)) {
		if (p_stat(path.ptr, &st) == 0) {
			/* check that we have not crossed device boundaries */
			if (initial_device == 0)
				initial_device = st.st_dev;
			else if (st.st_dev != initial_device &&
				(flags & GIT_REPOSITORY_OPEN_CROSS_FS) == 0)
				break;

			if (S_ISDIR(st.st_mode)) {
				if (valid_repository_path(&path)) {
					git_path_to_dir(&path);
					git_buf_set(repo_path, path.ptr, path.size);
					break;
				}
			}
			else if (S_ISREG(st.st_mode)) {
				git_buf repo_link = GIT_BUF_INIT;

				if (!(error = read_gitfile(&repo_link, path.ptr))) {
					if (valid_repository_path(&repo_link))
						git_buf_swap(repo_path, &repo_link);

					git_buf_free(&repo_link);
					break;
				}
				git_buf_free(&repo_link);
			}
		}

		/* move up one directory level */
		if (git_path_dirname_r(&path, path.ptr) < 0) {
			error = -1;
			break;
		}

		if (try_with_dot_git) {
			/* if we tried original dir with and without .git AND either hit
			 * directory ceiling or NO_SEARCH was requested, then be done.
			 */
			if (path.ptr[ceiling_offset] == '\0' ||
				(flags & GIT_REPOSITORY_OPEN_NO_SEARCH) != 0)
				break;
			/* otherwise look first for .git item */
			error = git_buf_joinpath(&path, path.ptr, DOT_GIT);
		}
		try_with_dot_git = !try_with_dot_git;
	}

	if (!error && parent_path && !(flags & GIT_REPOSITORY_OPEN_BARE)) {
		if (!git_buf_len(repo_path))
			git_buf_clear(parent_path);
		else {
			git_path_dirname_r(parent_path, path.ptr);
			git_path_to_dir(parent_path);
		}
		if (git_buf_oom(parent_path))
			return -1;
	}

	git_buf_free(&path);

	if (!git_buf_len(repo_path) && !error) {
		giterr_set(GITERR_REPOSITORY,
			"Could not find repository from '%s'", start_path);
		error = GIT_ENOTFOUND;
	}

	return error;
}