2 * Copyright (C) 2009-2011 the libgit2 contributors
4 * This file is part of libgit2, distributed under the GNU GPL v2 with
5 * a Linking Exception. For full terms see the included COPYING file.
9 #include "git2/object.h"
12 #include "repository.h"
20 #define GIT_OBJECTS_INFO_DIR GIT_OBJECTS_DIR "info/"
21 #define GIT_OBJECTS_PACK_DIR GIT_OBJECTS_DIR "pack/"
23 #define GIT_FILE_CONTENT_PREFIX "gitdir: "
25 #define GIT_BRANCH_MASTER "master"
28 * Git repository open methods
30 * Open a repository object from its path
32 static int assign_repository_dirs(
35 const char *git_object_directory
,
36 const char *git_index_file
,
37 const char *git_work_tree
)
39 char path_aux
[GIT_PATH_MAX
];
40 int error
= GIT_SUCCESS
;
45 return git__throw(GIT_ENOTFOUND
, "Failed to open repository. Git dir not found");
47 error
= git_path_prettify_dir(path_aux
, git_dir
, NULL
);
48 if (error
< GIT_SUCCESS
)
49 return git__rethrow(error
, "Failed to open repository");
52 repo
->path_repository
= git__strdup(path_aux
);
53 if (repo
->path_repository
== NULL
)
56 /* path to GIT_OBJECT_DIRECTORY */
57 if (git_object_directory
== NULL
)
58 git_path_join(path_aux
, repo
->path_repository
, GIT_OBJECTS_DIR
);
60 error
= git_path_prettify_dir(path_aux
, git_object_directory
, NULL
);
61 if (error
< GIT_SUCCESS
)
62 return git__rethrow(error
, "Failed to open repository");
65 /* Store GIT_OBJECT_DIRECTORY */
66 repo
->path_odb
= git__strdup(path_aux
);
67 if (repo
->path_odb
== NULL
)
70 /* path to GIT_WORK_TREE */
71 if (git_work_tree
== NULL
)
74 error
= git_path_prettify_dir(path_aux
, git_work_tree
, NULL
);
75 if (error
< GIT_SUCCESS
)
76 return git__rethrow(error
, "Failed to open repository");
78 /* Store GIT_WORK_TREE */
79 repo
->path_workdir
= git__strdup(path_aux
);
80 if (repo
->path_workdir
== NULL
)
83 /* Path to GIT_INDEX_FILE */
84 if (git_index_file
== NULL
)
85 git_path_join(path_aux
, repo
->path_repository
, GIT_INDEX_FILE
);
87 error
= git_path_prettify(path_aux
, git_index_file
, NULL
);
88 if (error
< GIT_SUCCESS
)
89 return git__rethrow(error
, "Failed to open repository");
92 /* store GIT_INDEX_FILE */
93 repo
->path_index
= git__strdup(path_aux
);
94 if (repo
->path_index
== NULL
)
101 static int check_repository_dirs(git_repository
*repo
)
103 char path_aux
[GIT_PATH_MAX
];
105 if (git_futils_isdir(repo
->path_repository
) < GIT_SUCCESS
)
106 return git__throw(GIT_ENOTAREPO
, "`%s` is not a folder", repo
->path_repository
);
108 /* Ensure GIT_OBJECT_DIRECTORY exists */
109 if (git_futils_isdir(repo
->path_odb
) < GIT_SUCCESS
)
110 return git__throw(GIT_ENOTAREPO
, "`%s` does not exist", repo
->path_odb
);
112 /* Ensure HEAD file exists */
113 git_path_join(path_aux
, repo
->path_repository
, GIT_HEAD_FILE
);
114 if (git_futils_isfile(path_aux
) < 0)
115 return git__throw(GIT_ENOTAREPO
, "HEAD file is missing");
120 static int guess_repository_dirs(git_repository
*repo
, const char *repository_path
)
122 char buffer
[GIT_PATH_MAX
];
123 const char *path_work_tree
= NULL
;
125 /* Git directory name */
126 if (git_path_basename_r(buffer
, sizeof(buffer
), repository_path
) < 0)
127 return git__throw(GIT_EINVALIDPATH
, "Unable to parse folder name from `%s`", repository_path
);
129 if (strcmp(buffer
, DOT_GIT
) == 0) {
130 /* Path to working dir */
131 if (git_path_dirname_r(buffer
, sizeof(buffer
), repository_path
) < 0)
132 return git__throw(GIT_EINVALIDPATH
, "Unable to parse parent folder name from `%s`", repository_path
);
133 path_work_tree
= buffer
;
136 return assign_repository_dirs(repo
, repository_path
, NULL
, NULL
, path_work_tree
);
139 static int quickcheck_repository_dir(const char *repository_path
)
141 char path_aux
[GIT_PATH_MAX
];
143 /* Ensure HEAD file exists */
144 git_path_join(path_aux
, repository_path
, GIT_HEAD_FILE
);
145 if (git_futils_isfile(path_aux
) < 0)
148 git_path_join(path_aux
, repository_path
, GIT_OBJECTS_DIR
);
149 if (git_futils_isdir(path_aux
) < 0)
152 git_path_join(path_aux
, repository_path
, GIT_REFS_DIR
);
153 if (git_futils_isdir(path_aux
) < 0)
159 static git_repository
*repository_alloc(void)
163 git_repository
*repo
= git__malloc(sizeof(git_repository
));
167 memset(repo
, 0x0, sizeof(git_repository
));
169 error
= git_cache_init(&repo
->objects
, GIT_DEFAULT_CACHE_SIZE
, &git_object__free
);
170 if (error
< GIT_SUCCESS
) {
175 if (git_repository__refcache_init(&repo
->references
) < GIT_SUCCESS
) {
183 static int init_odb(git_repository
*repo
)
185 return git_odb_open(&repo
->db
, repo
->path_odb
);
188 int git_repository_open3(git_repository
**repo_out
,
190 git_odb
*object_database
,
191 const char *git_index_file
,
192 const char *git_work_tree
)
194 git_repository
*repo
;
195 int error
= GIT_SUCCESS
;
199 if (object_database
== NULL
)
200 return git__throw(GIT_EINVALIDARGS
, "Failed to open repository. `object_database` can't be null");
202 repo
= repository_alloc();
206 error
= assign_repository_dirs(repo
,
212 if (error
< GIT_SUCCESS
)
215 error
= check_repository_dirs(repo
);
216 if (error
< GIT_SUCCESS
)
219 repo
->db
= object_database
;
225 git_repository_free(repo
);
226 return git__rethrow(error
, "Failed to open repository");
230 int git_repository_open2(git_repository
**repo_out
,
232 const char *git_object_directory
,
233 const char *git_index_file
,
234 const char *git_work_tree
)
236 git_repository
*repo
;
237 int error
= GIT_SUCCESS
;
241 repo
= repository_alloc();
245 error
= assign_repository_dirs(repo
,
247 git_object_directory
,
251 if (error
< GIT_SUCCESS
)
254 error
= check_repository_dirs(repo
);
255 if (error
< GIT_SUCCESS
)
258 error
= init_odb(repo
);
259 if (error
< GIT_SUCCESS
)
266 git_repository_free(repo
);
267 return git__rethrow(error
, "Failed to open repository");
270 int git_repository_config(
272 git_repository
*repo
,
273 const char *global_config_path
,
274 const char *system_config_path
)
276 char config_path
[GIT_PATH_MAX
];
281 error
= git_config_new(out
);
282 if (error
< GIT_SUCCESS
)
285 git_path_join(config_path
, repo
->path_repository
, GIT_CONFIG_FILENAME_INREPO
);
286 error
= git_config_add_file_ondisk(*out
, config_path
, 3);
287 if (error
< GIT_SUCCESS
)
290 if (global_config_path
!= NULL
) {
291 error
= git_config_add_file_ondisk(*out
, global_config_path
, 2);
292 if (error
< GIT_SUCCESS
)
296 if (system_config_path
!= NULL
) {
297 error
= git_config_add_file_ondisk(*out
, system_config_path
, 1);
298 if (error
< GIT_SUCCESS
)
306 git_config_free(*out
);
310 int git_repository_config_autoload(
312 git_repository
*repo
)
314 char global
[GIT_PATH_MAX
], system
[GIT_PATH_MAX
];
315 char *global_path
, *system_path
;
319 error
= git_config_find_global(global
);
320 global_path
= error
< GIT_SUCCESS
? NULL
: global
;
322 error
= git_config_find_system(system
);
323 system_path
= error
< GIT_SUCCESS
? NULL
: system
;
325 return git_repository_config(out
, repo
, global_path
, system_path
);
328 static int discover_repository_dirs(git_repository
*repo
, const char *path
)
332 error
= guess_repository_dirs(repo
, path
);
333 if (error
< GIT_SUCCESS
)
336 error
= check_repository_dirs(repo
);
337 if (error
< GIT_SUCCESS
)
343 int git_repository_open(git_repository
**repo_out
, const char *path
)
345 git_repository
*repo
;
346 int error
= GIT_SUCCESS
;
348 assert(repo_out
&& path
);
350 repo
= repository_alloc();
354 error
= discover_repository_dirs(repo
, path
);
355 if (error
< GIT_SUCCESS
)
358 error
= init_odb(repo
);
359 if (error
< GIT_SUCCESS
)
366 git_repository_free(repo
);
367 return git__rethrow(error
, "Failed to open repository");
370 static int retrieve_device(dev_t
*device_out
, const char *path
)
372 struct stat path_info
;
376 if (p_lstat(path
, &path_info
))
377 return git__throw(GIT_EOSERR
, "Failed to get file informations: %s", path
);
379 *device_out
= path_info
.st_dev
;
384 static int retrieve_ceiling_directories_offset(const char *path
, const char *ceiling_directories
)
386 char buf
[GIT_PATH_MAX
+ 1];
387 char buf2
[GIT_PATH_MAX
+ 1];
388 const char *ceil
, *sep
;
389 int len
, max_len
= -1;
394 min_len
= git_path_root(path
) + 1;
396 if (ceiling_directories
== NULL
|| min_len
== 0)
399 for (sep
= ceil
= ceiling_directories
; *sep
; ceil
= sep
+ 1) {
400 for (sep
= ceil
; *sep
&& *sep
!= GIT_PATH_LIST_SEPARATOR
; sep
++);
403 if (len
== 0 || len
> GIT_PATH_MAX
|| git_path_root(ceil
) == -1)
406 strncpy(buf
, ceil
, len
);
409 if (p_realpath(buf
, buf2
) == NULL
)
413 if (len
> 0 && buf2
[len
-1] == '/')
416 if (!strncmp(path
, buf2
, len
) &&
424 return max_len
<= min_len
? min_len
: max_len
;
427 static int read_gitfile(char *path_out
, const char *file_path
, const char *base_path
)
434 assert(path_out
&& file_path
&& base_path
);
436 error
= git_futils_readbuffer(&file
, file_path
);
438 if (error
< GIT_SUCCESS
)
441 data
= (char*)(file
.data
);
443 if (git__prefixcmp(data
, GIT_FILE_CONTENT_PREFIX
)) {
444 git_futils_freebuffer(&file
);
445 return git__throw(GIT_ENOTFOUND
, "Invalid gitfile format `%s`", file_path
);
448 end_offset
= strlen(data
) - 1;
450 for (;data
[end_offset
] == '\r' || data
[end_offset
] == '\n'; --end_offset
);
451 data
[end_offset
+ 1] = '\0';
453 if (strlen(GIT_FILE_CONTENT_PREFIX
) == end_offset
+ 1) {
454 git_futils_freebuffer(&file
);
455 return git__throw(GIT_ENOTFOUND
, "No path in git file `%s`", file_path
);
458 data
= data
+ strlen(GIT_FILE_CONTENT_PREFIX
);
459 error
= git_path_prettify_dir(path_out
, data
, base_path
);
460 git_futils_freebuffer(&file
);
462 if (error
== 0 && git_futils_exists(path_out
) == 0)
465 return git__throw(GIT_EOBJCORRUPTED
, "The `.git` file points to an inexisting path");
468 static void git_repository__free_dirs(git_repository
*repo
)
470 free(repo
->path_workdir
);
471 repo
->path_workdir
= NULL
;
472 free(repo
->path_index
);
473 repo
->path_index
= NULL
;
474 free(repo
->path_repository
);
475 repo
->path_repository
= NULL
;
476 free(repo
->path_odb
);
477 repo
->path_odb
= NULL
;
480 void git_repository_free(git_repository
*repo
)
485 git_cache_free(&repo
->objects
);
486 git_repository__refcache_free(&repo
->references
);
487 git_repository__free_dirs(repo
);
489 if (repo
->db
!= NULL
)
490 git_odb_close(repo
->db
);
495 int git_repository_discover(char *repository_path
, size_t size
, const char *start_path
, int across_fs
, const char *ceiling_dirs
)
497 int error
, ceiling_offset
;
498 char bare_path
[GIT_PATH_MAX
];
499 char normal_path
[GIT_PATH_MAX
];
501 dev_t current_device
= 0;
503 assert(start_path
&& repository_path
);
505 error
= git_path_prettify_dir(bare_path
, start_path
, NULL
);
506 if (error
< GIT_SUCCESS
)
510 error
= retrieve_device(¤t_device
, bare_path
);
511 if (error
< GIT_SUCCESS
)
515 ceiling_offset
= retrieve_ceiling_directories_offset(bare_path
, ceiling_dirs
);
516 git_path_join(normal_path
, bare_path
, DOT_GIT
);
520 * If the `.git` file is regular instead of
521 * a directory, it should contain the path of the actual git repository
523 if (git_futils_isfile(normal_path
) == GIT_SUCCESS
) {
524 error
= read_gitfile(repository_path
, normal_path
, bare_path
);
526 if (error
< GIT_SUCCESS
)
527 return git__rethrow(error
, "Unable to read git file `%s`", normal_path
);
529 error
= quickcheck_repository_dir(repository_path
);
530 if (error
< GIT_SUCCESS
)
531 return git__throw(GIT_ENOTFOUND
, "The `.git` file found at '%s' points"
532 "to an inexisting Git folder", normal_path
);
538 * If the `.git` file is a folder, we check inside of it
540 if (git_futils_isdir(normal_path
) == GIT_SUCCESS
) {
541 error
= quickcheck_repository_dir(normal_path
);
542 if (error
== GIT_SUCCESS
) {
543 found_path
= normal_path
;
549 * Otherwise, the repository may be bare, let's check
552 error
= quickcheck_repository_dir(bare_path
);
553 if (error
== GIT_SUCCESS
) {
554 found_path
= bare_path
;
558 if (git_path_dirname_r(normal_path
, sizeof(normal_path
), bare_path
) < GIT_SUCCESS
)
559 return git__throw(GIT_EOSERR
, "Failed to dirname '%s'", bare_path
);
563 error
= retrieve_device(&new_device
, normal_path
);
565 if (error
< GIT_SUCCESS
|| current_device
!= new_device
) {
566 return git__throw(GIT_ENOTAREPO
,"Not a git repository (or any parent up to mount parent %s)\n"
567 "Stopping at filesystem boundary.", bare_path
);
569 current_device
= new_device
;
572 strcpy(bare_path
, normal_path
);
573 git_path_join(normal_path
, bare_path
, DOT_GIT
);
575 // nothing has been found, lets try the parent directory
576 if (bare_path
[ceiling_offset
] == '\0') {
577 return git__throw(GIT_ENOTAREPO
,"Not a git repository (or any of the parent directories): %s", start_path
);
581 if (size
< strlen(found_path
) + 2) {
582 return git__throw(GIT_ESHORTBUFFER
, "The repository buffer is not long enough to handle the repository path `%s`", found_path
);
585 git_path_join(repository_path
, found_path
, "");
589 git_odb
*git_repository_database(git_repository
*repo
)
595 static int repo_init_reinit(const char *repository_path
, int is_bare
)
597 /* TODO: reinit the repository */
598 return git__throw(GIT_ENOTIMPLEMENTED
,
599 "Failed to reinitialize the %srepository at '%s'. "
600 "This feature is not yet implemented",
601 is_bare
? "bare" : "", repository_path
);
604 static int repo_init_createhead(git_repository
*repo
)
606 git_reference
*head_reference
;
607 return git_reference_create_symbolic(&head_reference
, repo
, GIT_HEAD_FILE
, GIT_REFS_HEADS_MASTER_FILE
, 0);
610 static int repo_init_structure(const char *git_dir
, int is_bare
)
612 const int mode
= 0755; /* or 0777 ? */
615 char temp_path
[GIT_PATH_MAX
];
617 if (git_futils_mkdir_r(git_dir
, mode
))
618 return git__throw(GIT_ERROR
, "Failed to initialize repository structure. Could not mkdir");
620 /* Hides the ".git" directory */
623 error
= p_hide_directory__w32(git_dir
);
624 if (error
< GIT_SUCCESS
)
625 return git__rethrow(error
, "Failed to initialize repository structure");
629 /* Creates the '/objects/info/' directory */
630 git_path_join(temp_path
, git_dir
, GIT_OBJECTS_INFO_DIR
);
631 error
= git_futils_mkdir_r(temp_path
, mode
);
632 if (error
< GIT_SUCCESS
)
633 return git__rethrow(error
, "Failed to initialize repository structure");
635 /* Creates the '/objects/pack/' directory */
636 git_path_join(temp_path
, git_dir
, GIT_OBJECTS_PACK_DIR
);
637 error
= p_mkdir(temp_path
, mode
);
638 if (error
< GIT_SUCCESS
)
639 return git__throw(error
, "Unable to create `%s` folder", temp_path
);
641 /* Creates the '/refs/heads/' directory */
642 git_path_join(temp_path
, git_dir
, GIT_REFS_HEADS_DIR
);
643 error
= git_futils_mkdir_r(temp_path
, mode
);
644 if (error
< GIT_SUCCESS
)
645 return git__rethrow(error
, "Failed to initialize repository structure");
647 /* Creates the '/refs/tags/' directory */
648 git_path_join(temp_path
, git_dir
, GIT_REFS_TAGS_DIR
);
649 error
= p_mkdir(temp_path
, mode
);
650 if (error
< GIT_SUCCESS
)
651 return git__throw(error
, "Unable to create `%s` folder", temp_path
);
653 /* TODO: what's left? templates? */
658 int git_repository_init(git_repository
**repo_out
, const char *path
, unsigned is_bare
)
660 int error
= GIT_SUCCESS
;
661 git_repository
*repo
= NULL
;
662 char repository_path
[GIT_PATH_MAX
];
664 assert(repo_out
&& path
);
666 git_path_join(repository_path
, path
, is_bare
? "" : GIT_DIR
);
668 if (git_futils_isdir(repository_path
)) {
669 if (quickcheck_repository_dir(repository_path
) == GIT_SUCCESS
)
670 return repo_init_reinit(repository_path
, is_bare
);
673 error
= repo_init_structure(repository_path
, is_bare
);
674 if (error
< GIT_SUCCESS
)
677 repo
= repository_alloc();
683 error
= guess_repository_dirs(repo
, repository_path
);
684 if (error
< GIT_SUCCESS
)
687 assert(repo
->is_bare
== is_bare
);
689 error
= init_odb(repo
);
690 if (error
< GIT_SUCCESS
)
693 error
= repo_init_createhead(repo
);
694 if (error
< GIT_SUCCESS
)
697 /* should never fail */
698 assert(check_repository_dirs(repo
) == GIT_SUCCESS
);
704 git_repository_free(repo
);
705 return git__rethrow(error
, "Failed to (re)init the repository `%s`", path
);
708 int git_repository_head_detached(git_repository
*repo
)
712 size_t GIT_UNUSED(_size
);
715 error
= git_reference_lookup(&ref
, repo
, GIT_HEAD_FILE
);
716 if (error
< GIT_SUCCESS
)
719 if (git_reference_type(ref
) == GIT_REF_SYMBOLIC
)
722 error
= git_odb_read_header(&_size
, &type
, repo
->db
, git_reference_oid(ref
));
723 if (error
< GIT_SUCCESS
)
726 if (type
!= GIT_OBJ_COMMIT
)
727 return git__throw(GIT_EOBJCORRUPTED
, "HEAD is not a commit");
732 int git_repository_head(git_reference
**head_out
, git_repository
*repo
)
739 error
= git_reference_lookup(&ref
, repo
, GIT_HEAD_FILE
);
740 if (error
< GIT_SUCCESS
)
741 return git__rethrow(GIT_ENOTAREPO
, "Failed to locate the HEAD");
743 error
= git_reference_resolve(&ref
, ref
);
744 if (error
< GIT_SUCCESS
)
745 return git__rethrow(error
, "Failed to resolve the HEAD");
751 int git_repository_head_orphan(git_repository
*repo
)
756 error
= git_repository_head(&ref
, repo
);
758 return error
== GIT_ENOTFOUND
? 1 : error
;
761 int git_repository_is_empty(git_repository
*repo
)
763 git_reference
*head
, *branch
;
766 error
= git_reference_lookup(&head
, repo
, "HEAD");
767 if (error
< GIT_SUCCESS
)
768 return git__throw(error
, "Corrupted repository. HEAD does not exist");
770 if (git_reference_type(head
) != GIT_REF_SYMBOLIC
)
773 if (strcmp(git_reference_target(head
), "refs/heads/master") != 0)
776 error
= git_reference_resolve(&branch
, head
);
777 return error
== GIT_ENOTFOUND
? 1 : error
;
780 const char *git_repository_path(git_repository
*repo
, git_repository_pathid id
)
786 return repo
->path_repository
;
788 case GIT_REPO_PATH_INDEX
:
789 return repo
->path_index
;
791 case GIT_REPO_PATH_ODB
:
792 return repo
->path_odb
;
794 case GIT_REPO_PATH_WORKDIR
:
795 return repo
->path_workdir
;
802 int git_repository_is_bare(git_repository
*repo
)
805 return repo
->is_bare
;