mirror of
https://git.proxmox.com/git/libgit2
synced 2025-05-03 15:27:01 +00:00
Refactored the opening and the initialization of a repository.
This commit is contained in:
parent
3b3a10176e
commit
d2d6912e6c
@ -16,6 +16,9 @@
|
|||||||
#define GIT_PACKEDREFS_HEADER "# pack-refs with: peeled "
|
#define GIT_PACKEDREFS_HEADER "# pack-refs with: peeled "
|
||||||
#define MAX_GITDIR_TREE_STRUCTURE_PATH_LENGTH 100
|
#define MAX_GITDIR_TREE_STRUCTURE_PATH_LENGTH 100
|
||||||
|
|
||||||
|
#define GIT_HEAD_FILE "HEAD"
|
||||||
|
#define GIT_REFS_HEADS_MASTER_FILE GIT_REFS_HEADS_DIR "master"
|
||||||
|
|
||||||
struct git_reference {
|
struct git_reference {
|
||||||
git_repository *owner;
|
git_repository *owner;
|
||||||
char *name;
|
char *name;
|
||||||
|
254
src/repository.c
254
src/repository.c
@ -35,14 +35,9 @@
|
|||||||
|
|
||||||
#include "refs.h"
|
#include "refs.h"
|
||||||
|
|
||||||
#define GIT_DIR ".git/"
|
|
||||||
#define GIT_OBJECTS_DIR "objects/"
|
|
||||||
#define GIT_OBJECTS_INFO_DIR GIT_OBJECTS_DIR "info/"
|
#define GIT_OBJECTS_INFO_DIR GIT_OBJECTS_DIR "info/"
|
||||||
#define GIT_OBJECTS_PACK_DIR GIT_OBJECTS_DIR "pack/"
|
#define GIT_OBJECTS_PACK_DIR GIT_OBJECTS_DIR "pack/"
|
||||||
|
|
||||||
#define GIT_INDEX_FILE "index"
|
|
||||||
#define GIT_HEAD_FILE "HEAD"
|
|
||||||
|
|
||||||
#define GIT_BRANCH_MASTER "master"
|
#define GIT_BRANCH_MASTER "master"
|
||||||
|
|
||||||
static const int OBJECT_TABLE_SIZE = 32;
|
static const int OBJECT_TABLE_SIZE = 32;
|
||||||
@ -77,7 +72,8 @@ static int assign_repository_DIRs(git_repository *repo,
|
|||||||
const char *git_dir,
|
const char *git_dir,
|
||||||
const char *git_object_directory,
|
const char *git_object_directory,
|
||||||
const char *git_index_file,
|
const char *git_index_file,
|
||||||
const char *git_work_tree)
|
const char *git_work_tree,
|
||||||
|
int is_repo_being_created)
|
||||||
{
|
{
|
||||||
char path_aux[GIT_PATH_MAX];
|
char path_aux[GIT_PATH_MAX];
|
||||||
size_t git_dir_path_len;
|
size_t git_dir_path_len;
|
||||||
@ -92,9 +88,6 @@ static int assign_repository_DIRs(git_repository *repo,
|
|||||||
if (error < GIT_SUCCESS)
|
if (error < GIT_SUCCESS)
|
||||||
return error;
|
return error;
|
||||||
|
|
||||||
if (gitfo_isdir(path_aux) < GIT_SUCCESS)
|
|
||||||
return GIT_ENOTFOUND;
|
|
||||||
|
|
||||||
git_dir_path_len = strlen(path_aux);
|
git_dir_path_len = strlen(path_aux);
|
||||||
|
|
||||||
/* store GIT_DIR */
|
/* store GIT_DIR */
|
||||||
@ -102,124 +95,94 @@ static int assign_repository_DIRs(git_repository *repo,
|
|||||||
if (repo->path_repository == NULL)
|
if (repo->path_repository == NULL)
|
||||||
return GIT_ENOMEM;
|
return GIT_ENOMEM;
|
||||||
|
|
||||||
/* store GIT_OBJECT_DIRECTORY */
|
/* path to GIT_OBJECT_DIRECTORY */
|
||||||
if (git_object_directory == NULL)
|
if (git_object_directory == NULL)
|
||||||
strcpy(repo->path_repository + git_dir_path_len, GIT_OBJECTS_DIR);
|
git__joinpath(path_aux, repo->path_repository, GIT_OBJECTS_DIR);
|
||||||
else {
|
else {
|
||||||
error = gitfo_prettify_dir_path(path_aux, git_object_directory);
|
error = gitfo_prettify_dir_path(path_aux, git_object_directory);
|
||||||
if (error < GIT_SUCCESS)
|
if (error < GIT_SUCCESS)
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Ensure GIT_OBJECT_DIRECTORY exists */
|
||||||
if (gitfo_isdir(path_aux) < GIT_SUCCESS)
|
if (gitfo_isdir(path_aux) < GIT_SUCCESS)
|
||||||
return GIT_ENOTFOUND;
|
return GIT_ENOTFOUND;
|
||||||
|
|
||||||
|
/* Store GIT_OBJECT_DIRECTORY */
|
||||||
repo->path_odb = git__strdup(path_aux);
|
repo->path_odb = git__strdup(path_aux);
|
||||||
if (repo->path_odb == NULL)
|
if (repo->path_odb == NULL)
|
||||||
return GIT_ENOMEM;
|
return GIT_ENOMEM;
|
||||||
|
|
||||||
/* store GIT_INDEX_FILE */
|
if (!is_repo_being_created) {
|
||||||
if (git_index_file == NULL)
|
/* Ensure HEAD file exists */
|
||||||
strcpy(repo->path_repository + git_dir_path_len, GIT_INDEX_FILE);
|
git__joinpath(path_aux, repo->path_repository, GIT_HEAD_FILE);
|
||||||
else {
|
if (gitfo_exists(path_aux) < 0)
|
||||||
error = gitfo_prettify_file_path(path_aux, git_index_file);
|
return GIT_ENOTAREPO;
|
||||||
if (error < GIT_SUCCESS)
|
|
||||||
return error;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gitfo_exists(path_aux) < 0)
|
/* path to GIT_WORK_TREE */
|
||||||
return GIT_ENOTFOUND;
|
|
||||||
|
|
||||||
repo->path_index = git__strdup(path_aux);
|
|
||||||
if (repo->path_index == NULL)
|
|
||||||
return GIT_ENOMEM;
|
|
||||||
|
|
||||||
/* store GIT_WORK_TREE */
|
|
||||||
if (git_work_tree == NULL)
|
if (git_work_tree == NULL)
|
||||||
repo->is_bare = 1;
|
repo->is_bare = 1;
|
||||||
else {
|
else {
|
||||||
error = gitfo_prettify_dir_path(path_aux, git_work_tree);
|
error = gitfo_prettify_dir_path(path_aux, git_work_tree);
|
||||||
if (error < GIT_SUCCESS)
|
if (error < GIT_SUCCESS)
|
||||||
return error;
|
return error;
|
||||||
|
|
||||||
|
/* Store GIT_WORK_TREE */
|
||||||
repo->path_workdir = git__strdup(path_aux);
|
repo->path_workdir = git__strdup(path_aux);
|
||||||
if (repo->path_workdir == NULL)
|
if (repo->path_workdir == NULL)
|
||||||
return GIT_ENOMEM;
|
return GIT_ENOMEM;
|
||||||
|
|
||||||
|
/* Path to GIT_INDEX_FILE */
|
||||||
|
if (git_index_file == NULL)
|
||||||
|
git__joinpath(path_aux, repo->path_repository, GIT_INDEX_FILE);
|
||||||
|
else {
|
||||||
|
error = gitfo_prettify_file_path(path_aux, git_index_file);
|
||||||
|
if (error < GIT_SUCCESS)
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!is_repo_being_created) {
|
||||||
|
/* Ensure GIT_INDEX_FILE exists */
|
||||||
|
if (gitfo_exists(path_aux) < 0)
|
||||||
|
return GIT_ENOTAREPO;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* store GIT_INDEX_FILE */
|
||||||
|
repo->path_index = git__strdup(path_aux);
|
||||||
|
if (repo->path_index == NULL)
|
||||||
|
return GIT_ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
return GIT_SUCCESS;
|
return GIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int guess_repository_DIRs(git_repository *repo, const char *repository_path)
|
static int guess_repository_DIRs(git_repository *repo, const char *repository_path, int is_repo_being_created)
|
||||||
{
|
{
|
||||||
char path_aux[GIT_PATH_MAX];
|
char path_odb[GIT_PATH_MAX] = "\0", path_index[GIT_PATH_MAX] = "\0", path_work_tree[GIT_PATH_MAX] = "\0";
|
||||||
const char *topdir;
|
char dir_name[MAX_GITDIR_TREE_STRUCTURE_PATH_LENGTH];
|
||||||
|
|
||||||
int path_len;
|
|
||||||
int error = GIT_SUCCESS;
|
int error = GIT_SUCCESS;
|
||||||
|
|
||||||
error = gitfo_prettify_dir_path(path_aux, repository_path);
|
/* Path to objects database */
|
||||||
if (error < GIT_SUCCESS)
|
git__joinpath(path_odb, repository_path, GIT_OBJECTS_DIR);
|
||||||
|
|
||||||
|
/* Git directory name */
|
||||||
|
if (git__basename_r(dir_name, sizeof(dir_name), repository_path) < 0)
|
||||||
|
return GIT_EINVALIDPATH;
|
||||||
|
|
||||||
|
if (strcmp(dir_name, DOT_GIT) == 0) {
|
||||||
|
|
||||||
|
/* Path to index file */
|
||||||
|
git__joinpath(path_index, repository_path, GIT_INDEX_FILE);
|
||||||
|
|
||||||
|
/* Path to working dir */
|
||||||
|
if (git__dirname_r(path_work_tree, sizeof(path_work_tree), repository_path) < 0)
|
||||||
|
return GIT_EINVALIDPATH;
|
||||||
|
}
|
||||||
|
|
||||||
|
error = assign_repository_DIRs(repo, repository_path, path_odb, !*path_index ? NULL : path_index, !*path_work_tree ? NULL : path_work_tree, is_repo_being_created);
|
||||||
return error;
|
return error;
|
||||||
|
|
||||||
if (gitfo_isdir(path_aux) < GIT_SUCCESS)
|
|
||||||
return GIT_ENOTAREPO;
|
|
||||||
|
|
||||||
path_len = strlen(path_aux);
|
|
||||||
|
|
||||||
repo->path_repository = git__strdup(path_aux);
|
|
||||||
if (repo->path_repository == NULL)
|
|
||||||
return GIT_ENOMEM;
|
|
||||||
|
|
||||||
/* objects database */
|
|
||||||
strcpy(path_aux + path_len, GIT_OBJECTS_DIR);
|
|
||||||
if (gitfo_isdir(path_aux) < GIT_SUCCESS)
|
|
||||||
return GIT_ENOTAREPO;
|
|
||||||
repo->path_odb = git__strdup(path_aux);
|
|
||||||
if (repo->path_odb == NULL)
|
|
||||||
return GIT_ENOMEM;
|
|
||||||
|
|
||||||
/* HEAD file */
|
|
||||||
strcpy(path_aux + path_len, GIT_HEAD_FILE);
|
|
||||||
if (gitfo_exists(path_aux) < 0)
|
|
||||||
return GIT_ENOTAREPO;
|
|
||||||
|
|
||||||
path_aux[path_len] = 0;
|
|
||||||
|
|
||||||
if ((topdir = git__topdir(path_aux)) == NULL)
|
|
||||||
return GIT_EINVALIDPATH;
|
|
||||||
|
|
||||||
if (strcmp(topdir, GIT_DIR) == 0) {
|
|
||||||
int workdir_len;
|
|
||||||
|
|
||||||
repo->is_bare = 0;
|
|
||||||
|
|
||||||
/* index file */
|
|
||||||
strcpy(path_aux + path_len, GIT_INDEX_FILE);
|
|
||||||
repo->path_index = git__strdup(path_aux);
|
|
||||||
if (repo->path_index == NULL)
|
|
||||||
return GIT_ENOMEM;
|
|
||||||
|
|
||||||
/* working dir */
|
|
||||||
path_aux[path_len] = 0;
|
|
||||||
workdir_len = git__dirname_r(path_aux, GIT_PATH_MAX, path_aux);
|
|
||||||
if (workdir_len < 0)
|
|
||||||
return GIT_EINVALIDPATH;
|
|
||||||
|
|
||||||
if (path_aux[workdir_len - 1] != '/') {
|
|
||||||
path_aux[workdir_len] = '/';
|
|
||||||
path_aux[workdir_len + 1] = '\0';
|
|
||||||
}
|
|
||||||
|
|
||||||
repo->path_workdir = git__strdup(path_aux);
|
|
||||||
if (repo->path_workdir == NULL)
|
|
||||||
return GIT_ENOMEM;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
repo->is_bare = 1;
|
|
||||||
repo->path_workdir = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return GIT_SUCCESS;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static git_repository *repository_alloc()
|
static git_repository *repository_alloc()
|
||||||
@ -276,7 +239,8 @@ int git_repository_open3(git_repository **repo_out,
|
|||||||
git_dir,
|
git_dir,
|
||||||
NULL,
|
NULL,
|
||||||
git_index_file,
|
git_index_file,
|
||||||
git_work_tree);
|
git_work_tree,
|
||||||
|
0);
|
||||||
|
|
||||||
if (error < GIT_SUCCESS)
|
if (error < GIT_SUCCESS)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
@ -311,7 +275,8 @@ int git_repository_open2(git_repository **repo_out,
|
|||||||
git_dir,
|
git_dir,
|
||||||
git_object_directory,
|
git_object_directory,
|
||||||
git_index_file,
|
git_index_file,
|
||||||
git_work_tree);
|
git_work_tree,
|
||||||
|
0);
|
||||||
|
|
||||||
if (error < GIT_SUCCESS)
|
if (error < GIT_SUCCESS)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
@ -328,31 +293,36 @@ cleanup:
|
|||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int repository_open_internal(git_repository **repo_out, const char *path, int is_repo_being_created)
|
||||||
|
{
|
||||||
|
git_repository *repo;
|
||||||
|
int error = GIT_SUCCESS;
|
||||||
|
|
||||||
|
assert(repo_out && path);
|
||||||
|
|
||||||
|
repo = repository_alloc();
|
||||||
|
if (repo == NULL)
|
||||||
|
return GIT_ENOMEM;
|
||||||
|
|
||||||
|
error = guess_repository_DIRs(repo, path, is_repo_being_created);
|
||||||
|
if (error < GIT_SUCCESS)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
error = init_odb(repo);
|
||||||
|
if (error < GIT_SUCCESS)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
*repo_out = repo;
|
||||||
|
return GIT_SUCCESS;
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
git_repository_free(repo);
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
int git_repository_open(git_repository **repo_out, const char *path)
|
int git_repository_open(git_repository **repo_out, const char *path)
|
||||||
{
|
{
|
||||||
git_repository *repo;
|
return repository_open_internal(repo_out, path, 0);
|
||||||
int error = GIT_SUCCESS;
|
|
||||||
|
|
||||||
assert(repo_out && path);
|
|
||||||
|
|
||||||
repo = repository_alloc();
|
|
||||||
if (repo == NULL)
|
|
||||||
return GIT_ENOMEM;
|
|
||||||
|
|
||||||
error = guess_repository_DIRs(repo, path);
|
|
||||||
if (error < GIT_SUCCESS)
|
|
||||||
goto cleanup;
|
|
||||||
|
|
||||||
error = init_odb(repo);
|
|
||||||
if (error < GIT_SUCCESS)
|
|
||||||
goto cleanup;
|
|
||||||
|
|
||||||
*repo_out = repo;
|
|
||||||
return GIT_SUCCESS;
|
|
||||||
|
|
||||||
cleanup:
|
|
||||||
git_repository_free(repo);
|
|
||||||
return error;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void git_repository_free(git_repository *repo)
|
void git_repository_free(git_repository *repo)
|
||||||
@ -535,21 +505,18 @@ static int repo_init_reinit(repo_init *results)
|
|||||||
return GIT_SUCCESS;
|
return GIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int repo_init_createhead(const char *head_path)
|
static int repo_init_createhead(git_repository *repo)
|
||||||
{
|
{
|
||||||
git_file fd;
|
git_reference *head_reference;
|
||||||
int error = GIT_SUCCESS;
|
return git_reference_create_symbolic(&head_reference, repo, GIT_HEAD_FILE, GIT_REFS_HEADS_MASTER_FILE);
|
||||||
char head_symlink[50];
|
}
|
||||||
|
|
||||||
sprintf(head_symlink, "%s %s%s\n", GIT_SYMREF, GIT_REFS_HEADS_DIR, GIT_BRANCH_MASTER);
|
static int repo_init_check_head_existence(char * repository_path)
|
||||||
|
{
|
||||||
|
char temp_path[GIT_PATH_MAX];
|
||||||
|
|
||||||
if ((fd = gitfo_creat(head_path, S_IREAD | S_IWRITE)) < GIT_SUCCESS)
|
git__joinpath(temp_path, repository_path, GIT_HEAD_FILE);
|
||||||
return GIT_ERROR;
|
return gitfo_exists(temp_path);
|
||||||
|
|
||||||
error = gitfo_write(fd, (void*)head_symlink, strlen(head_symlink));
|
|
||||||
|
|
||||||
gitfo_close(fd);
|
|
||||||
return error;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int repo_init_structure(repo_init *results)
|
static int repo_init_structure(repo_init *results)
|
||||||
@ -557,24 +524,11 @@ static int repo_init_structure(repo_init *results)
|
|||||||
const int mode = 0755; /* or 0777 ? */
|
const int mode = 0755; /* or 0777 ? */
|
||||||
|
|
||||||
char temp_path[GIT_PATH_MAX];
|
char temp_path[GIT_PATH_MAX];
|
||||||
int path_len;
|
|
||||||
char *git_dir = results->path_repository;
|
char *git_dir = results->path_repository;
|
||||||
|
|
||||||
if (gitfo_mkdir_recurs(git_dir, mode))
|
if (gitfo_mkdir_recurs(git_dir, mode))
|
||||||
return GIT_ERROR;
|
return GIT_ERROR;
|
||||||
|
|
||||||
path_len = strlen(git_dir);
|
|
||||||
strcpy(temp_path, git_dir);
|
|
||||||
|
|
||||||
/* Does HEAD file already exist ? */
|
|
||||||
git__joinpath(temp_path, git_dir, GIT_HEAD_FILE);
|
|
||||||
|
|
||||||
if (gitfo_exists(temp_path) == GIT_SUCCESS)
|
|
||||||
return repo_init_reinit(results);
|
|
||||||
|
|
||||||
if (repo_init_createhead(temp_path) < GIT_SUCCESS)
|
|
||||||
return GIT_ERROR;
|
|
||||||
|
|
||||||
/* Creates the '/objects/info/' directory */
|
/* Creates the '/objects/info/' directory */
|
||||||
git__joinpath(temp_path, git_dir, GIT_OBJECTS_INFO_DIR);
|
git__joinpath(temp_path, git_dir, GIT_OBJECTS_INFO_DIR);
|
||||||
if (gitfo_mkdir_recurs(temp_path, mode) < GIT_SUCCESS)
|
if (gitfo_mkdir_recurs(temp_path, mode) < GIT_SUCCESS)
|
||||||
@ -609,11 +563,6 @@ static int repo_init_find_dir(repo_init *results, const char* path)
|
|||||||
if (error < GIT_SUCCESS)
|
if (error < GIT_SUCCESS)
|
||||||
return error;
|
return error;
|
||||||
|
|
||||||
/*
|
|
||||||
if (gitfo_isdir(temp_path) < GIT_SUCCESS)
|
|
||||||
return GIT_ENOTAREPO;
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (!results->is_bare) {
|
if (!results->is_bare) {
|
||||||
git__joinpath(temp_path, temp_path, GIT_DIR);
|
git__joinpath(temp_path, temp_path, GIT_DIR);
|
||||||
}
|
}
|
||||||
@ -639,11 +588,20 @@ int git_repository_init(git_repository **repo_out, const char *path, unsigned is
|
|||||||
if (error < GIT_SUCCESS)
|
if (error < GIT_SUCCESS)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
|
if (!repo_init_check_head_existence(results.path_repository))
|
||||||
|
return repo_init_reinit(&results);
|
||||||
|
|
||||||
error = repo_init_structure(&results);
|
error = repo_init_structure(&results);
|
||||||
if (error < GIT_SUCCESS)
|
if (error < GIT_SUCCESS)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
error = git_repository_open(repo_out, results.path_repository);
|
error = repository_open_internal(repo_out, results.path_repository, 1);
|
||||||
|
if (error < GIT_SUCCESS)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
assert((*repo_out)->is_bare == is_bare);
|
||||||
|
|
||||||
|
error = repo_init_createhead(*repo_out);
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
free(results.path_repository);
|
free(results.path_repository);
|
||||||
|
@ -10,6 +10,11 @@
|
|||||||
#include "index.h"
|
#include "index.h"
|
||||||
#include "refs.h"
|
#include "refs.h"
|
||||||
|
|
||||||
|
#define DOT_GIT ".git"
|
||||||
|
#define GIT_DIR DOT_GIT "/"
|
||||||
|
#define GIT_OBJECTS_DIR "objects/"
|
||||||
|
#define GIT_INDEX_FILE "index"
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
git_rawobj raw;
|
git_rawobj raw;
|
||||||
void *write_ptr;
|
void *write_ptr;
|
||||||
|
Loading…
Reference in New Issue
Block a user