mirror of
https://git.proxmox.com/git/libgit2
synced 2025-05-29 17:05:49 +00:00
Add new method git_reference_listall
Lists all the references in a repository. Listing may be filtered by reference type. This should applease Lord Clem.
This commit is contained in:
parent
58d06cf120
commit
0057182807
@ -27,6 +27,7 @@
|
||||
|
||||
#include "thread-utils.h"
|
||||
#include <time.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
# define GIT_BEGIN_DECL extern "C" {
|
||||
@ -158,6 +159,21 @@
|
||||
#define GIT_EINVALIDREFSTATE (GIT_ERROR - 21)
|
||||
|
||||
GIT_BEGIN_DECL
|
||||
|
||||
typedef struct {
|
||||
char **strings;
|
||||
size_t count;
|
||||
} git_strarray;
|
||||
|
||||
GIT_INLINE(void) git_strarray_free(git_strarray *array)
|
||||
{
|
||||
size_t i;
|
||||
for (i = 0; i < array->count; ++i)
|
||||
free(array->strings[i]);
|
||||
|
||||
free(array->strings);
|
||||
}
|
||||
|
||||
/** @} */
|
||||
GIT_END_DECL
|
||||
#endif
|
||||
|
@ -218,6 +218,29 @@ GIT_EXTERN(int) git_reference_delete(git_reference *ref);
|
||||
*/
|
||||
GIT_EXTERN(int) git_reference_packall(git_repository *repo);
|
||||
|
||||
/**
|
||||
* Fill a list with all the references that can be found
|
||||
* in a repository.
|
||||
*
|
||||
* The listed references may be filtered by type, or using
|
||||
* a bitwise OR of several types. Use the magic value
|
||||
* `GIT_REF_LISTALL` to obtain all references, including
|
||||
* packed ones.
|
||||
*
|
||||
* The string array will be filled with the names of all
|
||||
* references; these values are owned by the user and
|
||||
* should be free'd manually when no longer needed, using
|
||||
* `git_strarray_free`.
|
||||
*
|
||||
* @param array Pointer to a git_strarray structure where
|
||||
* the reference names will be stored
|
||||
* @param repo Repository where to find the refs
|
||||
* @param list_flags Filtering flags for the reference
|
||||
* listing.
|
||||
* @return 0 on success; error code otherwise
|
||||
*/
|
||||
GIT_EXTERN(int) git_reference_listall(git_strarray *array, git_repository *repo, unsigned int list_flags);
|
||||
|
||||
/** @} */
|
||||
GIT_END_DECL
|
||||
#endif
|
||||
|
@ -145,6 +145,7 @@ typedef enum {
|
||||
GIT_REF_SYMBOLIC = 2, /** A reference which points at another reference */
|
||||
GIT_REF_PACKED = 4,
|
||||
GIT_REF_HAS_PEEL = 8,
|
||||
GIT_REF_LISTALL = GIT_REF_OID|GIT_REF_SYMBOLIC|GIT_REF_PACKED,
|
||||
} git_rtype;
|
||||
|
||||
/** @} */
|
||||
|
82
src/refs.c
82
src/refs.c
@ -235,6 +235,24 @@ static int loose_read(gitfo_buf *file_content, const char *name, const char *rep
|
||||
return error;
|
||||
}
|
||||
|
||||
static git_rtype loose_guess_rtype(const char *full_path)
|
||||
{
|
||||
gitfo_buf ref_file = GITFO_BUF_INIT;
|
||||
git_rtype type;
|
||||
|
||||
type = GIT_REF_INVALID;
|
||||
|
||||
if (gitfo_read_file(&ref_file, full_path) == GIT_SUCCESS) {
|
||||
if (git__prefixcmp((const char *)(ref_file.data), GIT_SYMREF) == 0)
|
||||
type = GIT_REF_SYMBOLIC;
|
||||
else
|
||||
type = GIT_REF_OID;
|
||||
}
|
||||
|
||||
gitfo_free_buf(&ref_file);
|
||||
return type;
|
||||
}
|
||||
|
||||
static int loose_lookup(
|
||||
git_reference **ref_out,
|
||||
git_repository *repo,
|
||||
@ -531,6 +549,31 @@ cleanup:
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
struct dirent_list_data {
|
||||
git_vector ref_list;
|
||||
size_t repo_path_len;
|
||||
unsigned int list_flags;
|
||||
};
|
||||
|
||||
static int _dirent_loose_listall(void *_data, char *full_path)
|
||||
{
|
||||
struct dirent_list_data *data = (struct dirent_list_data *)_data;
|
||||
char *file_path;
|
||||
|
||||
if (gitfo_isdir(full_path) == GIT_SUCCESS)
|
||||
return gitfo_dirent(full_path, GIT_PATH_MAX, _dirent_loose_listall, _data);
|
||||
|
||||
if ((data->list_flags & loose_guess_rtype(full_path)) == 0)
|
||||
return GIT_SUCCESS; /* we are filtering out this reference */
|
||||
|
||||
file_path = full_path + data->repo_path_len;
|
||||
|
||||
return git_vector_insert(&data->ref_list, git__strdup(file_path));
|
||||
}
|
||||
|
||||
static int _dirent_loose_load(void *data, char *full_path)
|
||||
{
|
||||
git_repository *repository = (git_repository *)data;
|
||||
@ -1292,6 +1335,45 @@ int git_reference_packall(git_repository *repo)
|
||||
return packed_write(repo);
|
||||
}
|
||||
|
||||
int git_reference_listall(git_strarray *array, git_repository *repo, unsigned int list_flags)
|
||||
{
|
||||
int error;
|
||||
struct dirent_list_data data;
|
||||
char refs_path[GIT_PATH_MAX];
|
||||
|
||||
array->strings = NULL;
|
||||
array->count = 0;
|
||||
|
||||
git_vector_init(&data.ref_list, 8, NULL);
|
||||
data.repo_path_len = strlen(repo->path_repository);
|
||||
data.list_flags = list_flags;
|
||||
|
||||
git__joinpath(refs_path, repo->path_repository, GIT_REFS_DIR);
|
||||
error = gitfo_dirent(refs_path, GIT_PATH_MAX, _dirent_loose_listall, &data);
|
||||
|
||||
if (error < GIT_SUCCESS) {
|
||||
git_vector_free(&data.ref_list);
|
||||
return error;
|
||||
}
|
||||
|
||||
if (list_flags & GIT_REF_PACKED) {
|
||||
const char *ref_name;
|
||||
void *_unused;
|
||||
|
||||
if ((error = packed_load(repo)) < GIT_SUCCESS) {
|
||||
git_vector_free(&data.ref_list);
|
||||
return error;
|
||||
}
|
||||
|
||||
GIT_HASHTABLE_FOREACH(repo->references.packfile, ref_name, _unused,
|
||||
git_vector_insert(&data.ref_list, git__strdup(ref_name));
|
||||
);
|
||||
}
|
||||
|
||||
array->strings = (char **)data.ref_list.contents;
|
||||
array->count = data.ref_list.length;
|
||||
return GIT_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -710,6 +710,18 @@ BEGIN_TEST(normalize2, "tests borrowed from JGit")
|
||||
must_fail(ensure_refname_normalized(SYM_REF, "refs/heads/master@{1.hour.ago}", NULL));
|
||||
END_TEST
|
||||
|
||||
BEGIN_TEST(list0, "try to list all the references in our test repo")
|
||||
git_repository *repo;
|
||||
git_strarray ref_list;
|
||||
|
||||
must_pass(git_repository_open(&repo, REPOSITORY_FOLDER));
|
||||
must_pass(git_reference_listall(&ref_list, repo, GIT_REF_LISTALL));
|
||||
must_be_true(ref_list.count == 8); /* 8 refs in total if we include the packed ones */
|
||||
|
||||
git_strarray_free(&ref_list);
|
||||
git_repository_free(repo);
|
||||
END_TEST
|
||||
|
||||
|
||||
BEGIN_SUITE(refs)
|
||||
ADD_TEST(readtag0);
|
||||
@ -741,4 +753,5 @@ BEGIN_SUITE(refs)
|
||||
ADD_TEST(rename4);
|
||||
|
||||
ADD_TEST(delete0);
|
||||
ADD_TEST(list0);
|
||||
END_SUITE
|
||||
|
Loading…
Reference in New Issue
Block a user