int git_repository_open_bare( git_repository **repo_ptr, const char *bare_path) { int error; git_buf path = GIT_BUF_INIT; git_repository *repo = NULL; if ((error = git_path_prettify_dir(&path, bare_path, NULL)) < 0) return error; if (!valid_repository_path(&path)) { git_buf_free(&path); giterr_set(GITERR_REPOSITORY, "Path is not a repository: %s", bare_path); return GIT_ENOTFOUND; } repo = repository_alloc(); GITERR_CHECK_ALLOC(repo); repo->path_repository = git_buf_detach(&path); GITERR_CHECK_ALLOC(repo->path_repository); /* of course we're bare! */ repo->is_bare = 1; repo->workdir = NULL; *repo_ptr = repo; return 0; }
int git_repository_init(git_repository **repo_out, const char *path, unsigned is_bare) { git_buf repository_path = GIT_BUF_INIT; assert(repo_out && path); if (git_buf_joinpath(&repository_path, path, is_bare ? "" : GIT_DIR) < 0) return -1; if (git_path_isdir(repository_path.ptr) == true) { if (valid_repository_path(&repository_path) == true) { int res = repo_init_reinit(repo_out, repository_path.ptr, is_bare); git_buf_free(&repository_path); return res; } } if (repo_init_structure(repository_path.ptr, is_bare) < 0 || repo_init_config(repository_path.ptr, is_bare) < 0 || repo_init_createhead(repository_path.ptr) < 0 || git_repository_open(repo_out, repository_path.ptr) < 0) { git_buf_free(&repository_path); return -1; } git_buf_free(&repository_path); return 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; }