Skip to content

Commit 3d22394

Browse files
authored
Merge pull request libgit2#4967 from tiennou/fix/4671
Incomplete commondir support
2 parents c544850 + 501c51b commit 3d22394

File tree

7 files changed

+76
-70
lines changed

7 files changed

+76
-70
lines changed

include/git2/repository.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -438,7 +438,8 @@ typedef enum {
438438
GIT_REPOSITORY_ITEM_HOOKS,
439439
GIT_REPOSITORY_ITEM_LOGS,
440440
GIT_REPOSITORY_ITEM_MODULES,
441-
GIT_REPOSITORY_ITEM_WORKTREES
441+
GIT_REPOSITORY_ITEM_WORKTREES,
442+
GIT_REPOSITORY_ITEM__LAST
442443
} git_repository_item_t;
443444

444445
/**

include/git2/sys/repository.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,10 @@ GIT_BEGIN_DECL
2525
* Note that this is only useful if you wish to associate the repository
2626
* with a non-filesystem-backed object database and config store.
2727
*
28+
* Caveats: since this repository has no physical location, some systems
29+
* can fail to function properly: locations under $GIT_DIR, $GIT_COMMON_DIR,
30+
* or $GIT_INFO_DIR are impacted.
31+
*
2832
* @param out The blank repository
2933
* @return 0 on success, or an error code
3034
*/
@@ -39,7 +43,7 @@ GIT_EXTERN(int) git_repository_new(git_repository **out);
3943
* There's no need to call this function directly unless you're
4044
* trying to aggressively cleanup the repo before its
4145
* deallocation. `git_repository_free` already performs this operation
42-
* before deallocation the repo.
46+
* before deallocating the repo.
4347
*/
4448
GIT_EXTERN(void) git_repository__cleanup(git_repository *repo);
4549

src/attr.c

Lines changed: 33 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -306,53 +306,49 @@ static int system_attr_file(
306306

307307
static int attr_setup(git_repository *repo, git_attr_session *attr_session)
308308
{
309-
int error = 0;
310-
const char *workdir = git_repository_workdir(repo);
311-
git_index *idx = NULL;
312309
git_buf path = GIT_BUF_INIT;
310+
git_index *idx = NULL;
311+
const char *workdir;
312+
int error = 0;
313313

314314
if (attr_session && attr_session->init_setup)
315315
return 0;
316316

317317
if ((error = git_attr_cache__init(repo)) < 0)
318318
return error;
319319

320-
/* preload attribute files that could contain macros so the
321-
* definitions will be available for later file parsing
320+
/*
321+
* Preload attribute files that could contain macros so the
322+
* definitions will be available for later file parsing.
322323
*/
323324

324-
error = system_attr_file(&path, attr_session);
325-
326-
if (error == 0)
327-
error = preload_attr_file(
328-
repo, attr_session, GIT_ATTR_FILE__FROM_FILE, NULL, path.ptr);
329-
330-
if (error != GIT_ENOTFOUND)
331-
goto out;
332-
333-
if ((error = preload_attr_file(
334-
repo, attr_session, GIT_ATTR_FILE__FROM_FILE,
335-
NULL, git_repository_attr_cache(repo)->cfg_attr_file)) < 0)
336-
goto out;
325+
if ((error = system_attr_file(&path, attr_session)) < 0 ||
326+
(error = preload_attr_file(repo, attr_session, GIT_ATTR_FILE__FROM_FILE,
327+
NULL, path.ptr)) < 0) {
328+
if (error != GIT_ENOTFOUND)
329+
goto out;
330+
}
337331

338-
if ((error = git_repository_item_path(&path,
339-
repo, GIT_REPOSITORY_ITEM_INFO)) < 0)
332+
if ((error = preload_attr_file(repo, attr_session, GIT_ATTR_FILE__FROM_FILE,
333+
NULL, git_repository_attr_cache(repo)->cfg_attr_file)) < 0)
340334
goto out;
341335

342-
if ((error = preload_attr_file(
343-
repo, attr_session, GIT_ATTR_FILE__FROM_FILE,
344-
path.ptr, GIT_ATTR_FILE_INREPO)) < 0)
345-
goto out;
336+
if ((error = git_repository_item_path(&path, repo, GIT_REPOSITORY_ITEM_INFO)) < 0 ||
337+
(error = preload_attr_file(repo, attr_session, GIT_ATTR_FILE__FROM_FILE,
338+
path.ptr, GIT_ATTR_FILE_INREPO)) < 0) {
339+
if (error != GIT_ENOTFOUND)
340+
goto out;
341+
}
346342

347-
if (workdir != NULL &&
348-
(error = preload_attr_file(
349-
repo, attr_session, GIT_ATTR_FILE__FROM_FILE, workdir, GIT_ATTR_FILE)) < 0)
350-
goto out;
343+
if ((workdir = git_repository_workdir(repo)) != NULL &&
344+
(error = preload_attr_file(repo, attr_session, GIT_ATTR_FILE__FROM_FILE,
345+
workdir, GIT_ATTR_FILE)) < 0)
346+
goto out;
351347

352348
if ((error = git_repository_index__weakptr(&idx, repo)) < 0 ||
353-
(error = preload_attr_file(
354-
repo, attr_session, GIT_ATTR_FILE__FROM_INDEX, NULL, GIT_ATTR_FILE)) < 0)
355-
goto out;
349+
(error = preload_attr_file(repo, attr_session, GIT_ATTR_FILE__FROM_INDEX,
350+
NULL, GIT_ATTR_FILE)) < 0)
351+
goto out;
356352

357353
if (attr_session)
358354
attr_session->init_setup = 1;
@@ -516,15 +512,12 @@ static int collect_attr_files(
516512
* - $GIT_PREFIX/etc/gitattributes
517513
*/
518514

519-
error = git_repository_item_path(&attrfile, repo, GIT_REPOSITORY_ITEM_INFO);
520-
if (error < 0)
521-
goto cleanup;
522-
523-
error = push_attr_file(
524-
repo, attr_session, files, GIT_ATTR_FILE__FROM_FILE,
525-
attrfile.ptr, GIT_ATTR_FILE_INREPO);
526-
if (error < 0)
527-
goto cleanup;
515+
if ((error = git_repository_item_path(&attrfile, repo, GIT_REPOSITORY_ITEM_INFO)) < 0 ||
516+
(error = push_attr_file(repo, attr_session, files, GIT_ATTR_FILE__FROM_FILE,
517+
attrfile.ptr, GIT_ATTR_FILE_INREPO)) < 0) {
518+
if (error != GIT_ENOTFOUND)
519+
goto cleanup;
520+
}
528521

529522
info.repo = repo;
530523
info.attr_session = attr_session;

src/ignore.c

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -335,16 +335,13 @@ int git_ignore__for_path(
335335
goto cleanup;
336336
}
337337

338-
if ((error = git_repository_item_path(&infopath,
339-
repo, GIT_REPOSITORY_ITEM_INFO)) < 0)
340-
goto cleanup;
341-
342-
/* load .git/info/exclude */
343-
error = push_ignore_file(
344-
ignores, &ignores->ign_global,
345-
infopath.ptr, GIT_IGNORE_FILE_INREPO);
346-
if (error < 0)
347-
goto cleanup;
338+
/* load .git/info/exclude if possible */
339+
if ((error = git_repository_item_path(&infopath, repo, GIT_REPOSITORY_ITEM_INFO)) < 0 ||
340+
(error = push_ignore_file(ignores, &ignores->ign_global, infopath.ptr, GIT_IGNORE_FILE_INREPO)) < 0) {
341+
if (error != GIT_ENOTFOUND)
342+
goto cleanup;
343+
error = 0;
344+
}
348345

349346
/* load core.excludesfile */
350347
if (git_repository_attr_cache(repo)->cfg_excl_file != NULL)

src/odb.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -548,6 +548,7 @@ int git_odb__add_default_backends(
548548
#else
549549
if (p_stat(objects_dir, &st) < 0) {
550550
if (as_alternates)
551+
/* this should warn */
551552
return 0;
552553

553554
git_error_set(GIT_ERROR_ODB, "failed to load object database in '%s'", objects_dir);

src/odb.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ int git_odb__hashobj(git_oid *id, git_rawobj *obj);
7171
* Format the object header such as it would appear in the on-disk object
7272
*/
7373
int git_odb__format_object_header(size_t *out_len, char *hdr, size_t hdr_size, git_off_t obj_len, git_object_t obj_type);
74+
7475
/*
7576
* Hash an open file descriptor.
7677
* This is a performance call when the contents of a fd need to be hashed,
@@ -95,7 +96,7 @@ int git_odb__hashfd_filtered(
9596
* symlink, then the raw contents of the symlink will be hashed. Otherwise,
9697
* this will fallback to `git_odb__hashfd`.
9798
*
98-
* The hash type for this call is always `GIT_OBJIECT_BLOB` because
99+
* The hash type for this call is always `GIT_OBJECT_BLOB` because
99100
* symlinks may only point to blobs.
100101
*/
101102
int git_odb__hashlink(git_oid *out, const char *path);

src/repository.c

Lines changed: 26 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -42,23 +42,24 @@ bool git_repository__fsync_gitdir = false;
4242

4343
static const struct {
4444
git_repository_item_t parent;
45+
git_repository_item_t fallback;
4546
const char *name;
4647
bool directory;
4748
} items[] = {
48-
{ GIT_REPOSITORY_ITEM_GITDIR, NULL, true },
49-
{ GIT_REPOSITORY_ITEM_WORKDIR, NULL, true },
50-
{ GIT_REPOSITORY_ITEM_COMMONDIR, NULL, true },
51-
{ GIT_REPOSITORY_ITEM_GITDIR, "index", false },
52-
{ GIT_REPOSITORY_ITEM_COMMONDIR, "objects", true },
53-
{ GIT_REPOSITORY_ITEM_COMMONDIR, "refs", true },
54-
{ GIT_REPOSITORY_ITEM_COMMONDIR, "packed-refs", false },
55-
{ GIT_REPOSITORY_ITEM_COMMONDIR, "remotes", true },
56-
{ GIT_REPOSITORY_ITEM_COMMONDIR, "config", false },
57-
{ GIT_REPOSITORY_ITEM_COMMONDIR, "info", true },
58-
{ GIT_REPOSITORY_ITEM_COMMONDIR, "hooks", true },
59-
{ GIT_REPOSITORY_ITEM_COMMONDIR, "logs", true },
60-
{ GIT_REPOSITORY_ITEM_GITDIR, "modules", true },
61-
{ GIT_REPOSITORY_ITEM_COMMONDIR, "worktrees", true }
49+
{ GIT_REPOSITORY_ITEM_GITDIR, GIT_REPOSITORY_ITEM__LAST, NULL, true },
50+
{ GIT_REPOSITORY_ITEM_WORKDIR, GIT_REPOSITORY_ITEM__LAST, NULL, true },
51+
{ GIT_REPOSITORY_ITEM_COMMONDIR, GIT_REPOSITORY_ITEM__LAST, NULL, true },
52+
{ GIT_REPOSITORY_ITEM_GITDIR, GIT_REPOSITORY_ITEM__LAST, "index", false },
53+
{ GIT_REPOSITORY_ITEM_COMMONDIR, GIT_REPOSITORY_ITEM_GITDIR, "objects", true },
54+
{ GIT_REPOSITORY_ITEM_COMMONDIR, GIT_REPOSITORY_ITEM_GITDIR, "refs", true },
55+
{ GIT_REPOSITORY_ITEM_COMMONDIR, GIT_REPOSITORY_ITEM_GITDIR, "packed-refs", false },
56+
{ GIT_REPOSITORY_ITEM_COMMONDIR, GIT_REPOSITORY_ITEM_GITDIR, "remotes", true },
57+
{ GIT_REPOSITORY_ITEM_COMMONDIR, GIT_REPOSITORY_ITEM_GITDIR, "config", false },
58+
{ GIT_REPOSITORY_ITEM_COMMONDIR, GIT_REPOSITORY_ITEM_GITDIR, "info", true },
59+
{ GIT_REPOSITORY_ITEM_COMMONDIR, GIT_REPOSITORY_ITEM_GITDIR, "hooks", true },
60+
{ GIT_REPOSITORY_ITEM_COMMONDIR, GIT_REPOSITORY_ITEM_GITDIR, "logs", true },
61+
{ GIT_REPOSITORY_ITEM_GITDIR, GIT_REPOSITORY_ITEM__LAST, "modules", true },
62+
{ GIT_REPOSITORY_ITEM_COMMONDIR, GIT_REPOSITORY_ITEM_GITDIR, "worktrees", true }
6263
};
6364

6465
static int check_repositoryformatversion(git_config *config);
@@ -2308,11 +2309,11 @@ int git_repository_is_empty(git_repository *repo)
23082309
return is_empty;
23092310
}
23102311

2311-
int git_repository_item_path(git_buf *out, const git_repository *repo, git_repository_item_t item)
2312+
static const char *resolved_parent_path(const git_repository *repo, git_repository_item_t item, git_repository_item_t fallback)
23122313
{
23132314
const char *parent;
23142315

2315-
switch (items[item].parent) {
2316+
switch (item) {
23162317
case GIT_REPOSITORY_ITEM_GITDIR:
23172318
parent = git_repository_path(repo);
23182319
break;
@@ -2324,9 +2325,17 @@ int git_repository_item_path(git_buf *out, const git_repository *repo, git_repos
23242325
break;
23252326
default:
23262327
git_error_set(GIT_ERROR_INVALID, "invalid item directory");
2327-
return -1;
2328+
return NULL;
23282329
}
2330+
if (!parent && fallback != GIT_REPOSITORY_ITEM__LAST)
2331+
return resolved_parent_path(repo, fallback, GIT_REPOSITORY_ITEM__LAST);
2332+
2333+
return parent;
2334+
}
23292335

2336+
int git_repository_item_path(git_buf *out, const git_repository *repo, git_repository_item_t item)
2337+
{
2338+
const char *parent = resolved_parent_path(repo, items[item].parent, items[item].fallback);
23302339
if (parent == NULL) {
23312340
git_error_set(GIT_ERROR_INVALID, "path cannot exist in repository");
23322341
return GIT_ENOTFOUND;

0 commit comments

Comments
 (0)