2 * This file is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License, version 2,
4 * as published by the Free Software Foundation.
6 * In addition to the permissions in the GNU General Public License,
7 * the authors give you unlimited permission to link the compiled
8 * version of this file into combinations with other programs,
9 * and to distribute those combinations without any restriction
10 * coming from the use of this file. (The General Public License
11 * restrictions do apply in other respects; for example, they cover
12 * modification of the file, and distribution when not linked into
13 * a combined executable.)
15 * This file is distributed in the hope that it will be useful, but
16 * WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; see the file COPYING. If not, write to
22 * the Free Software Foundation, 51 Franklin Street, Fifth Floor,
23 * Boston, MA 02110-1301, USA.
27 #include "git2/object.h"
30 #include "repository.h"
38 #define GIT_OBJECTS_INFO_DIR GIT_OBJECTS_DIR "info/"
39 #define GIT_OBJECTS_PACK_DIR GIT_OBJECTS_DIR "pack/"
41 #define GIT_BRANCH_MASTER "master"
44 char *path_repository
;
45 unsigned is_bare
:1, has_been_reinit
:1;
49 * Git repository open methods
51 * Open a repository object from its path
53 static int assign_repository_dirs(
56 const char *git_object_directory
,
57 const char *git_index_file
,
58 const char *git_work_tree
)
60 char path_aux
[GIT_PATH_MAX
];
61 size_t git_dir_path_len
;
62 int error
= GIT_SUCCESS
;
69 error
= gitfo_prettify_dir_path(path_aux
, git_dir
);
70 if (error
< GIT_SUCCESS
)
73 git_dir_path_len
= strlen(path_aux
);
76 repo
->path_repository
= git__strdup(path_aux
);
77 if (repo
->path_repository
== NULL
)
80 /* path to GIT_OBJECT_DIRECTORY */
81 if (git_object_directory
== NULL
)
82 git__joinpath(path_aux
, repo
->path_repository
, GIT_OBJECTS_DIR
);
84 error
= gitfo_prettify_dir_path(path_aux
, git_object_directory
);
85 if (error
< GIT_SUCCESS
)
89 /* Store GIT_OBJECT_DIRECTORY */
90 repo
->path_odb
= git__strdup(path_aux
);
91 if (repo
->path_odb
== NULL
)
94 /* path to GIT_WORK_TREE */
95 if (git_work_tree
== NULL
)
98 error
= gitfo_prettify_dir_path(path_aux
, git_work_tree
);
99 if (error
< GIT_SUCCESS
)
102 /* Store GIT_WORK_TREE */
103 repo
->path_workdir
= git__strdup(path_aux
);
104 if (repo
->path_workdir
== NULL
)
107 /* Path to GIT_INDEX_FILE */
108 if (git_index_file
== NULL
)
109 git__joinpath(path_aux
, repo
->path_repository
, GIT_INDEX_FILE
);
111 error
= gitfo_prettify_file_path(path_aux
, git_index_file
);
112 if (error
< GIT_SUCCESS
)
116 /* store GIT_INDEX_FILE */
117 repo
->path_index
= git__strdup(path_aux
);
118 if (repo
->path_index
== NULL
)
125 static int check_repository_dirs(git_repository
*repo
)
127 char path_aux
[GIT_PATH_MAX
];
129 if (gitfo_isdir(repo
->path_repository
) < GIT_SUCCESS
)
130 return GIT_ENOTAREPO
;
132 /* Ensure GIT_OBJECT_DIRECTORY exists */
133 if (gitfo_isdir(repo
->path_odb
) < GIT_SUCCESS
)
134 return GIT_ENOTAREPO
;
136 /* Ensure HEAD file exists */
137 git__joinpath(path_aux
, repo
->path_repository
, GIT_HEAD_FILE
);
138 if (gitfo_exists(path_aux
) < 0)
139 return GIT_ENOTAREPO
;
144 static int guess_repository_dirs(git_repository
*repo
, const char *repository_path
)
146 char buffer
[GIT_PATH_MAX
];
147 const char *path_work_tree
= NULL
;
149 /* Git directory name */
150 if (git__basename_r(buffer
, sizeof(buffer
), repository_path
) < 0)
151 return GIT_EINVALIDPATH
;
153 if (strcmp(buffer
, DOT_GIT
) == 0) {
154 /* Path to working dir */
155 if (git__dirname_r(buffer
, sizeof(buffer
), repository_path
) < 0)
156 return GIT_EINVALIDPATH
;
157 path_work_tree
= buffer
;
160 return assign_repository_dirs(repo
, repository_path
, NULL
, NULL
, path_work_tree
);
163 static git_repository
*repository_alloc()
165 git_repository
*repo
= git__malloc(sizeof(git_repository
));
169 memset(repo
, 0x0, sizeof(git_repository
));
171 git_cache_init(&repo
->objects
, GIT_DEFAULT_CACHE_SIZE
, &git_object__free
);
173 if (git_repository__refcache_init(&repo
->references
) < GIT_SUCCESS
) {
181 static int init_odb(git_repository
*repo
)
183 return git_odb_open(&repo
->db
, repo
->path_odb
);
186 int git_repository_open3(git_repository
**repo_out
,
188 git_odb
*object_database
,
189 const char *git_index_file
,
190 const char *git_work_tree
)
192 git_repository
*repo
;
193 int error
= GIT_SUCCESS
;
197 if (object_database
== NULL
)
200 repo
= repository_alloc();
204 error
= assign_repository_dirs(repo
,
210 if (error
< GIT_SUCCESS
)
213 error
= check_repository_dirs(repo
);
214 if (error
< GIT_SUCCESS
)
217 repo
->db
= object_database
;
223 git_repository_free(repo
);
228 int git_repository_open2(git_repository
**repo_out
,
230 const char *git_object_directory
,
231 const char *git_index_file
,
232 const char *git_work_tree
)
234 git_repository
*repo
;
235 int error
= GIT_SUCCESS
;
239 repo
= repository_alloc();
243 error
= assign_repository_dirs(repo
,
245 git_object_directory
,
249 if (error
< GIT_SUCCESS
)
252 error
= check_repository_dirs(repo
);
253 if (error
< GIT_SUCCESS
)
256 error
= init_odb(repo
);
257 if (error
< GIT_SUCCESS
)
264 git_repository_free(repo
);
268 int git_repository_open(git_repository
**repo_out
, const char *path
)
270 git_repository
*repo
;
271 int error
= GIT_SUCCESS
;
273 assert(repo_out
&& path
);
275 repo
= repository_alloc();
279 error
= guess_repository_dirs(repo
, path
);
280 if (error
< GIT_SUCCESS
)
283 error
= check_repository_dirs(repo
);
284 if (error
< GIT_SUCCESS
)
287 error
= init_odb(repo
);
288 if (error
< GIT_SUCCESS
)
295 git_repository_free(repo
);
299 void git_repository_free(git_repository
*repo
)
304 git_cache_free(&repo
->objects
);
305 git_repository__refcache_free(&repo
->references
);
307 free(repo
->path_workdir
);
308 free(repo
->path_index
);
309 free(repo
->path_repository
);
310 free(repo
->path_odb
);
312 if (repo
->db
!= NULL
)
313 git_odb_close(repo
->db
);
315 if (repo
->index
!= NULL
)
316 git_index_free(repo
->index
);
321 int git_repository_index(git_index
**index_out
, git_repository
*repo
)
325 assert(index_out
&& repo
);
327 if (repo
->index
== NULL
) {
328 error
= git_index_open_inrepo(&repo
->index
, repo
);
329 if (error
< GIT_SUCCESS
)
332 assert(repo
->index
!= NULL
);
335 *index_out
= repo
->index
;
339 git_odb
*git_repository_database(git_repository
*repo
)
345 static int repo_init_reinit(repo_init
*results
)
347 /* TODO: reinit the repository */
348 results
->has_been_reinit
= 1;
352 static int repo_init_createhead(git_repository
*repo
)
354 git_reference
*head_reference
;
355 return git_reference_create_symbolic(&head_reference
, repo
, GIT_HEAD_FILE
, GIT_REFS_HEADS_MASTER_FILE
);
358 static int repo_init_check_head_existence(char * repository_path
)
360 char temp_path
[GIT_PATH_MAX
];
362 git__joinpath(temp_path
, repository_path
, GIT_HEAD_FILE
);
363 return gitfo_exists(temp_path
);
366 static int repo_init_structure(repo_init
*results
)
368 const int mode
= 0755; /* or 0777 ? */
370 char temp_path
[GIT_PATH_MAX
];
371 char *git_dir
= results
->path_repository
;
373 if (gitfo_mkdir_recurs(git_dir
, mode
))
376 /* Creates the '/objects/info/' directory */
377 git__joinpath(temp_path
, git_dir
, GIT_OBJECTS_INFO_DIR
);
378 if (gitfo_mkdir_recurs(temp_path
, mode
) < GIT_SUCCESS
)
381 /* Creates the '/objects/pack/' directory */
382 git__joinpath(temp_path
, git_dir
, GIT_OBJECTS_PACK_DIR
);
383 if (gitfo_mkdir(temp_path
, mode
))
386 /* Creates the '/refs/heads/' directory */
387 git__joinpath(temp_path
, git_dir
, GIT_REFS_HEADS_DIR
);
388 if (gitfo_mkdir_recurs(temp_path
, mode
))
391 /* Creates the '/refs/tags/' directory */
392 git__joinpath(temp_path
, git_dir
, GIT_REFS_TAGS_DIR
);
393 if (gitfo_mkdir(temp_path
, mode
))
396 /* TODO: what's left? templates? */
401 static int repo_init_find_dir(repo_init
*results
, const char* path
)
403 char temp_path
[GIT_PATH_MAX
];
404 int error
= GIT_SUCCESS
;
406 error
= gitfo_prettify_dir_path(temp_path
, path
);
407 if (error
< GIT_SUCCESS
)
410 if (!results
->is_bare
) {
411 git__joinpath(temp_path
, temp_path
, GIT_DIR
);
414 results
->path_repository
= git__strdup(temp_path
);
415 if (results
->path_repository
== NULL
)
421 int git_repository_init(git_repository
**repo_out
, const char *path
, unsigned is_bare
)
423 int error
= GIT_SUCCESS
;
424 git_repository
*repo
= NULL
;
427 assert(repo_out
&& path
);
429 results
.path_repository
= NULL
;
430 results
.is_bare
= is_bare
;
432 error
= repo_init_find_dir(&results
, path
);
433 if (error
< GIT_SUCCESS
)
436 if (!repo_init_check_head_existence(results
.path_repository
))
437 return repo_init_reinit(&results
);
439 error
= repo_init_structure(&results
);
440 if (error
< GIT_SUCCESS
)
443 repo
= repository_alloc();
449 error
= guess_repository_dirs(repo
, results
.path_repository
);
450 if (error
< GIT_SUCCESS
)
453 assert(repo
->is_bare
== is_bare
);
455 error
= init_odb(repo
);
456 if (error
< GIT_SUCCESS
)
459 error
= repo_init_createhead(repo
);
460 if (error
< GIT_SUCCESS
)
463 /* should never fail */
464 assert(check_repository_dirs(repo
) == GIT_SUCCESS
);
466 free(results
.path_repository
);
471 free(results
.path_repository
);
472 git_repository_free(repo
);