summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/git2/odb.h2
-rw-r--r--include/git2/remote.h18
-rw-r--r--include/git2/repository.h232
-rw-r--r--src/blob.c23
-rw-r--r--src/commit.c7
-rw-r--r--src/common.h1
-rw-r--r--src/config.c15
-rw-r--r--src/config.h2
-rw-r--r--src/config_file.c3
-rw-r--r--src/fetch.c10
-rw-r--r--src/index.c53
-rw-r--r--src/index.h3
-rw-r--r--src/object.c23
-rw-r--r--src/odb.c16
-rw-r--r--src/odb.h2
-rw-r--r--src/refs.c19
-rw-r--r--src/remote.c18
-rw-r--r--src/repository.c597
-rw-r--r--src/repository.h12
-rw-r--r--src/revwalk.c11
-rw-r--r--src/status.c62
-rw-r--r--src/tag.c18
-rw-r--r--src/tree.c32
-rw-r--r--src/util.h24
-rw-r--r--tests-clay/clay.h45
-rw-r--r--tests-clay/clay_main.c108
-rw-r--r--tests-clay/config/add.c37
-rw-r--r--tests-clay/config/read.c209
-rw-r--r--tests-clay/config/stress.c12
-rw-r--r--tests-clay/config/write.c77
-rw-r--r--tests-clay/network/remotes.c42
-rw-r--r--tests-clay/object/tree/frompath.c7
-rw-r--r--tests-clay/odb/loose.c84
-rw-r--r--tests-clay/odb/loose_data.h (renamed from tests/t02-data.h)13
-rw-r--r--tests-clay/odb/pack_data.h (renamed from tests/t02-oids.h)1
-rw-r--r--tests-clay/odb/packed.c77
-rw-r--r--tests-clay/odb/sorting.c71
-rw-r--r--tests-clay/repo/getters.c68
-rw-r--r--tests-clay/repo/init.c104
-rw-r--r--tests-clay/repo/open.c54
-rw-r--r--tests/t02-objread.c269
-rw-r--r--tests/t03-objwrite.c14
-rw-r--r--tests/t12-repo.c291
-rw-r--r--tests/t15-config.c358
-rw-r--r--tests/t16-remotes.c107
-rw-r--r--tests/test_main.c6
46 files changed, 1593 insertions, 1664 deletions
diff --git a/include/git2/odb.h b/include/git2/odb.h
index 27837418b..b99c40e00 100644
--- a/include/git2/odb.h
+++ b/include/git2/odb.h
@@ -92,7 +92,7 @@ GIT_EXTERN(int) git_odb_add_alternate(git_odb *odb, git_odb_backend *backend, in
*
* @param db database pointer to close. If NULL no action is taken.
*/
-GIT_EXTERN(void) git_odb_close(git_odb *db);
+GIT_EXTERN(void) git_odb_free(git_odb *db);
/**
* Read an object from the database.
diff --git a/include/git2/remote.h b/include/git2/remote.h
index 43bbe9e1c..2bc2d16ec 100644
--- a/include/git2/remote.h
+++ b/include/git2/remote.h
@@ -39,7 +39,7 @@ GIT_BEGIN_DECL
* @param name the remote's name
* @return GIT_SUCCESS or an error code
*/
-int git_remote_new(git_remote **out, git_repository *repo, const char *url, const char *name);
+GIT_EXTERN(int) git_remote_new(git_remote **out, git_repository *repo, const char *url, const char *name);
/**
* Get the information for a particular remote
@@ -49,7 +49,7 @@ int git_remote_new(git_remote **out, git_repository *repo, const char *url, cons
* @param name the remote's name
* @return GIT_SUCCESS or an error code
*/
-GIT_EXTERN(int) git_remote_get(struct git_remote **out, struct git_config *cfg, const char *name);
+GIT_EXTERN(int) git_remote_load(git_remote **out, git_repository *repo, const char *name);
/**
* Get the remote's name
@@ -57,7 +57,7 @@ GIT_EXTERN(int) git_remote_get(struct git_remote **out, struct git_config *cfg,
* @param remote the remote
* @return a pointer to the name
*/
-GIT_EXTERN(const char *) git_remote_name(struct git_remote *remote);
+GIT_EXTERN(const char *) git_remote_name(git_remote *remote);
/**
* Get the remote's url
@@ -65,7 +65,7 @@ GIT_EXTERN(const char *) git_remote_name(struct git_remote *remote);
* @param remote the remote
* @return a pointer to the url
*/
-GIT_EXTERN(const char *) git_remote_url(struct git_remote *remote);
+GIT_EXTERN(const char *) git_remote_url(git_remote *remote);
/**
* Get the fetch refspec
@@ -73,7 +73,7 @@ GIT_EXTERN(const char *) git_remote_url(struct git_remote *remote);
* @param remote the remote
* @return a pointer to the fetch refspec or NULL if it doesn't exist
*/
-GIT_EXTERN(const git_refspec *) git_remote_fetchspec(struct git_remote *remote);
+GIT_EXTERN(const git_refspec *) git_remote_fetchspec(git_remote *remote);
/**
* Get the push refspec
@@ -82,7 +82,7 @@ GIT_EXTERN(const git_refspec *) git_remote_fetchspec(struct git_remote *remote);
* @return a pointer to the push refspec or NULL if it doesn't exist
*/
-GIT_EXTERN(const git_refspec *) git_remote_pushspec(struct git_remote *remote);
+GIT_EXTERN(const git_refspec *) git_remote_pushspec(git_remote *remote);
/**
* Open a connection to a remote
@@ -95,7 +95,7 @@ GIT_EXTERN(const git_refspec *) git_remote_pushspec(struct git_remote *remote);
* @param direction whether you want to receive or send data
* @return GIT_SUCCESS or an error code
*/
-GIT_EXTERN(int) git_remote_connect(struct git_remote *remote, int direction);
+GIT_EXTERN(int) git_remote_connect(git_remote *remote, int direction);
/**
* Get a list of refs at the remote
@@ -149,7 +149,7 @@ GIT_EXTERN(void) git_remote_disconnect(git_remote *remote);
*
* @param remote the remote to free
*/
-GIT_EXTERN(void) git_remote_free(struct git_remote *remote);
+GIT_EXTERN(void) git_remote_free(git_remote *remote);
/**
* Update the tips to the new state
@@ -159,7 +159,7 @@ GIT_EXTERN(void) git_remote_free(struct git_remote *remote);
*
* @param remote the remote to update
*/
-GIT_EXTERN(int) git_remote_update_tips(struct git_remote *remote);
+GIT_EXTERN(int) git_remote_update_tips(git_remote *remote);
/** @} */
GIT_END_DECL
diff --git a/include/git2/repository.h b/include/git2/repository.h
index 2e9baf6c0..bacb48145 100644
--- a/include/git2/repository.h
+++ b/include/git2/repository.h
@@ -23,21 +23,11 @@ GIT_BEGIN_DECL
/**
* Open a git repository.
*
- * The 'path' argument must point to an existing git repository
- * folder, e.g.
+ * The 'path' argument must point to either a git repository
+ * folder, or an existing work dir.
*
- * /path/to/my_repo/.git/ (normal repository)
- * objects/
- * index
- * HEAD
- *
- * /path/to/bare_repo/ (bare repository)
- * objects/
- * index
- * HEAD
- *
- * The method will automatically detect if 'path' is a normal
- * or bare repository or fail is 'path' is neither.
+ * The method will automatically detect if 'path' is a normal
+ * or bare repository or fail is 'path' is neither.
*
* @param repository pointer to the repo which will be opened
* @param path the path to the repository
@@ -45,130 +35,40 @@ GIT_BEGIN_DECL
*/
GIT_EXTERN(int) git_repository_open(git_repository **repository, const char *path);
-
-/**
- * Open a git repository by manually specifying all its paths
- *
- * @param repository pointer to the repo which will be opened
- *
- * @param git_dir The full path to the repository folder
- * e.g. a '.git' folder for live repos, any folder for bare
- * Equivalent to $GIT_DIR.
- * Cannot be NULL.
- *
- * @param git_object_directory The full path to the ODB folder.
- * the folder where all the loose and packed objects are stored
- * Equivalent to $GIT_OBJECT_DIRECTORY.
- * If NULL, "$GIT_DIR/objects/" is assumed.
- *
- * @param git_index_file The full path to the index (dircache) file
- * Equivalent to $GIT_INDEX_FILE.
- * If NULL, "$GIT_DIR/index" is assumed.
- *
- * @param git_work_tree The full path to the working tree of the repository,
- * if the repository is not bare.
- * Equivalent to $GIT_WORK_TREE.
- * If NULL, the repository is assumed to be bare.
- *
- * @return GIT_SUCCESS or an error code
- */
-GIT_EXTERN(int) git_repository_open2(git_repository **repository,
- const char *git_dir,
- const char *git_object_directory,
- const char *git_index_file,
- const char *git_work_tree);
-
-
-/**
- * Open a git repository by manually specifying its paths and
- * the object database it will use.
- *
- * @param repository pointer to the repo which will be opened
- *
- * @param git_dir The full path to the repository folder
- * e.g. a '.git' folder for live repos, any folder for bare
- * Equivalent to $GIT_DIR.
- * Cannot be NULL.
- *
- * @param object_database A pointer to a git_odb created & initialized
- * by the user (e.g. with custom backends). This object database
- * will be owned by the repository and will be automatically free'd.
- * It should not be manually free'd by the user, or this
- * git_repository object will become invalid.
- *
- * @param git_index_file The full path to the index (dircache) file
- * Equivalent to $GIT_INDEX_FILE.
- * If NULL, "$GIT_DIR/index" is assumed.
- *
- * @param git_work_tree The full path to the working tree of the repository,
- * if the repository is not bare.
- * Equivalent to $GIT_WORK_TREE.
- * If NULL, the repository is assumed to be bare.
- *
- * @return GIT_SUCCESS or an error code
- */
-
-GIT_EXTERN(int) git_repository_open3(git_repository **repository,
- const char *git_dir,
- git_odb *object_database,
- const char *git_index_file,
- const char *git_work_tree);
-
/**
- * Look for a git repository and copy its path in the given buffer. The lookup start
- * from base_path and walk across parent directories if nothing has been found. The
- * lookup ends when the first repository is found, or when reaching a directory
- * referenced in ceiling_dirs or when the filesystem changes (in case across_fs
- * is true).
+ * Look for a git repository and copy its path in the given buffer.
+ * The lookup start from base_path and walk across parent directories
+ * if nothing has been found. The lookup ends when the first repository
+ * is found, or when reaching a directory referenced in ceiling_dirs
+ * or when the filesystem changes (in case across_fs is true).
*
- * The method will automatically detect if the repository is bare (if there is
- * a repository).
+ * The method will automatically detect if the repository is bare
+ * (if there is a repository).
*
- * @param repository_path The user allocated buffer which will contain the found path.
+ * @param repository_path The user allocated buffer which will
+ * contain the found path.
*
* @param size repository_path size
*
* @param start_path The base path where the lookup starts.
*
- * @param across_fs If true, then the lookup will not stop when a filesystem device change
- * is detected while exploring parent directories.
+ * @param across_fs If true, then the lookup will not stop when a
+ * filesystem device change is detected while exploring parent directories.
*
- * @param ceiling_dirs A GIT_PATH_LIST_SEPARATOR separated list of absolute symbolic link
- * free paths. The lookup will stop when any of this paths is reached. Note that the
- * lookup always performs on start_path no matter start_path appears in ceiling_dirs
- * ceiling_dirs might be NULL (which is equivalent to an empty string)
+ * @param ceiling_dirs A GIT_PATH_LIST_SEPARATOR separated list of
+ * absolute symbolic link free paths. The lookup will stop when any
+ * of this paths is reached. Note that the lookup always performs on
+ * start_path no matter start_path appears in ceiling_dirs ceiling_dirs
+ * might be NULL (which is equivalent to an empty string)
*
* @return GIT_SUCCESS or an error code
*/
-GIT_EXTERN(int) git_repository_discover(char *repository_path, size_t size, const char *start_path, int across_fs, const char *ceiling_dirs);
-
-/**
- * Get the object database behind a Git repository
- *
- * @param repo a repository object
- * @return a pointer to the object db
- */
-GIT_EXTERN(git_odb *) git_repository_database(git_repository *repo);
-
-/**
- * Open the Index file of a Git repository
- *
- * This returns a new and unique `git_index` object representing the
- * active index for the repository.
- *
- * This method may be called more than once (e.g. on different threads).
- *
- * Each returned `git_index` object is independent and suffers no race
- * conditions: synchronization is done at the FS level.
- *
- * Each returned `git_index` object must be manually freed by the user,
- * using `git_index_free`.
- *
- * @param index Pointer where to store the index
- * @param repo a repository object
- * @return GIT_SUCCESS or an error code
- */
-GIT_EXTERN(int) git_repository_index(git_index **index, git_repository *repo);
+GIT_EXTERN(int) git_repository_discover(
+ char *repository_path,
+ size_t size,
+ const char *start_path,
+ int across_fs,
+ const char *ceiling_dirs);
/**
* Free a previously allocated repository
@@ -246,32 +146,9 @@ GIT_EXTERN(int) git_repository_head_orphan(git_repository *repo);
*/
GIT_EXTERN(int) git_repository_is_empty(git_repository *repo);
-/**
- * Internal path identifiers for a repository
- */
-typedef enum {
- GIT_REPO_PATH,
- GIT_REPO_PATH_INDEX,
- GIT_REPO_PATH_ODB,
- GIT_REPO_PATH_WORKDIR
-} git_repository_pathid;
-
-/**
- * Get one of the paths to the repository
- *
- * Possible values for `id`:
- *
- * GIT_REPO_PATH: return the path to the repository
- * GIT_REPO_PATH_INDEX: return the path to the index
- * GIT_REPO_PATH_ODB: return the path to the ODB
- * GIT_REPO_PATH_WORKDIR: return the path to the working
- * directory
- *
- * @param repo a repository object
- * @param id The ID of the path to return
- * @return absolute path of the requested id
- */
-GIT_EXTERN(const char *) git_repository_path(git_repository *repo, git_repository_pathid id);
+GIT_EXTERN(const char *) git_repository_path(git_repository *repo);
+GIT_EXTERN(const char *) git_repository_workdir(git_repository *repo);
+GIT_EXTERN(int) git_repository_set_workdir(git_repository *repo, const char *workdir);
/**
* Check if a repository is bare
@@ -281,53 +158,14 @@ GIT_EXTERN(const char *) git_repository_path(git_repository *repo, git_repositor
*/
GIT_EXTERN(int) git_repository_is_bare(git_repository *repo);
-/**
- * Retrieve the relevant configuration for a repository
- *
- * If either the `global_config_path` or `system_config_path`
- * variables are not NULL, the given config files will be also
- * included in the configuration set. The global configuration file is
- * located in $HOME/.gitconfig. On most UNIX systems, the system
- * config file file may be found on `$sysconfdir/gitconfig`.
- *
- * The resulting `git_config` instance will query the files in the following
- * order:
- *
- * - Repository configuration file
- * - Global configuration file
- * - System configuration file
- *
- * The method will fail if any of the given config files can't be
- * found or accessed.
- *
- * The returned `git_config` instance is owned by the caller and must
- * be manually free'd once it's no longer on use.
- *
- * @param out the repository's configuration
- * @param repo the repository for which to get the config
- * @param system_config_path Path to the global config file
- * @param system_config_path Path to the system-wide config file
- */
+GIT_EXTERN(int) git_repository_config(git_config **out, git_repository *repo);
+GIT_EXTERN(void) git_repository_set_config(git_repository *repo, git_config *config);
-GIT_EXTERN(int) git_repository_config(git_config **out,
- git_repository *repo,
- const char *global_config_path,
- const char *system_config_path);
+GIT_EXTERN(int) git_repository_odb(git_odb **out, git_repository *repo);
+GIT_EXTERN(void) git_repository_set_odb(git_repository *repo, git_odb *odb);
-/**
- * Automatically load the configuration files
- *
- * A wrapper around `git_repository_config` that tries to guess where
- * the global and system config files are located. No error is
- * reported if either of these files are missing at the guessed
- * locations.
- *
- * @param out the repository's configuration
- * @param repo the repository for which to get the config
- */
-GIT_EXTERN(int) git_repository_config_autoload(
- git_config **out,
- git_repository *repo);
+GIT_EXTERN(int) git_repository_index(git_index **out, git_repository *repo);
+GIT_EXTERN(void) git_repository_set_index(git_repository *repo, git_index *index);
/** @} */
GIT_END_DECL
diff --git a/src/blob.c b/src/blob.c
index f13a5be15..5fd0fd67e 100644
--- a/src/blob.c
+++ b/src/blob.c
@@ -41,9 +41,14 @@ int git_blob__parse(git_blob *blob, git_odb_object *odb_obj)
int git_blob_create_frombuffer(git_oid *oid, git_repository *repo, const void *buffer, size_t len)
{
int error;
+ git_odb *odb;
git_odb_stream *stream;
- if ((error = git_odb_open_wstream(&stream, repo->db, len, GIT_OBJ_BLOB)) < GIT_SUCCESS)
+ error = git_repository_odb__weakptr(&odb, repo);
+ if (error < GIT_SUCCESS)
+ return error;
+
+ if ((error = git_odb_open_wstream(&stream, odb, len, GIT_OBJ_BLOB)) < GIT_SUCCESS)
return git__rethrow(error, "Failed to create blob");
if ((error = stream->write(stream, buffer, len)) < GIT_SUCCESS) {
@@ -69,11 +74,14 @@ int git_blob_create_fromfile(git_oid *oid, git_repository *repo, const char *pat
git_off_t size;
git_odb_stream *stream;
struct stat st;
+ const char *workdir;
+ git_odb *odb;
- if (repo->path_workdir == NULL)
+ workdir = git_repository_workdir(repo);
+ if (workdir == NULL)
return git__throw(GIT_ENOTFOUND, "Failed to create blob. (No working directory found)");
- git_path_join(full_path, repo->path_workdir, path);
+ git_path_join(full_path, workdir, path);
error = p_lstat(full_path, &st);
if (error < 0) {
@@ -83,11 +91,16 @@ int git_blob_create_fromfile(git_oid *oid, git_repository *repo, const char *pat
islnk = S_ISLNK(st.st_mode);
size = st.st_size;
- if (!islnk)
+ error = git_repository_odb__weakptr(&odb, repo);
+ if (error < GIT_SUCCESS)
+ return error;
+
+ if (!islnk) {
if ((fd = p_open(full_path, O_RDONLY)) < 0)
return git__throw(GIT_ENOTFOUND, "Failed to create blob. Could not open '%s'", full_path);
+ }
- if ((error = git_odb_open_wstream(&stream, repo->db, (size_t)size, GIT_OBJ_BLOB)) < GIT_SUCCESS) {
+ if ((error = git_odb_open_wstream(&stream, odb, (size_t)size, GIT_OBJ_BLOB)) < GIT_SUCCESS) {
if (!islnk)
p_close(fd);
return git__rethrow(error, "Failed to create blob");
diff --git a/src/commit.c b/src/commit.c
index 83bc9fc4c..bf6ca7855 100644
--- a/src/commit.c
+++ b/src/commit.c
@@ -103,6 +103,7 @@ int git_commit_create(
{
git_buf commit = GIT_BUF_INIT;
int error, i;
+ git_odb *odb;
if (git_object_owner((const git_object *)tree) != repo)
return git__throw(GIT_EINVALIDARGS, "The given tree does not belong to this repository");
@@ -132,7 +133,11 @@ int git_commit_create(
goto cleanup;
}
- error = git_odb_write(oid, git_repository_database(repo), commit.ptr, commit.size, GIT_OBJ_COMMIT);
+ error = git_repository_odb__weakptr(&odb, repo);
+ if (error < GIT_SUCCESS)
+ goto cleanup;
+
+ error = git_odb_write(oid, odb, commit.ptr, commit.size, GIT_OBJ_COMMIT);
git_buf_free(&commit);
if (error == GIT_SUCCESS && update_ref != NULL) {
diff --git a/src/common.h b/src/common.h
index 727a08e77..35316012d 100644
--- a/src/common.h
+++ b/src/common.h
@@ -60,4 +60,5 @@ extern void git___rethrow(const char *, ...) GIT_FORMAT_PRINTF(1, 2);
#include "util.h"
+
#endif /* INCLUDE_common_h__ */
diff --git a/src/config.c b/src/config.c
index 4e48ff7f4..a8e15405b 100644
--- a/src/config.c
+++ b/src/config.c
@@ -22,15 +22,12 @@ typedef struct {
int priority;
} file_internal;
-void git_config_free(git_config *cfg)
+static void config_free(git_config *cfg)
{
unsigned int i;
git_config_file *file;
file_internal *internal;
- if (cfg == NULL)
- return;
-
for(i = 0; i < cfg->files.length; ++i){
internal = git_vector_get(&cfg->files, i);
file = internal->file;
@@ -42,6 +39,14 @@ void git_config_free(git_config *cfg)
git__free(cfg);
}
+void git_config_free(git_config *cfg)
+{
+ if (cfg == NULL)
+ return;
+
+ GIT_REFCOUNT_DEC(cfg, config_free);
+}
+
static int config_backend_cmp(const void *a, const void *b)
{
const file_internal *bk_a = (const file_internal *)(a);
@@ -66,7 +71,7 @@ int git_config_new(git_config **out)
}
*out = cfg;
-
+ GIT_REFCOUNT_INC(cfg);
return GIT_SUCCESS;
}
diff --git a/src/config.h b/src/config.h
index 43574a586..7f3494edc 100644
--- a/src/config.h
+++ b/src/config.h
@@ -17,8 +17,8 @@
#define GIT_CONFIG_FILE_MODE 0666
struct git_config {
+ git_refcount rc;
git_vector files;
- git_repository *repo;
};
#endif
diff --git a/src/config_file.c b/src/config_file.c
index 5e862d487..7a5865210 100644
--- a/src/config_file.c
+++ b/src/config_file.c
@@ -256,6 +256,7 @@ static int config_open(git_config_file *cfg)
diskfile_backend *b = (diskfile_backend *)cfg;
error = git_futils_readbuffer(&b->reader.buffer, b->file_path);
+
/* It's fine if the file doesn't exist */
if (error == GIT_ENOTFOUND)
return GIT_SUCCESS;
@@ -269,7 +270,7 @@ static int config_open(git_config_file *cfg)
git_futils_freebuffer(&b->reader.buffer);
- return error;
+ return GIT_SUCCESS;
cleanup:
cvar_list_free(&b->var_list);
diff --git a/src/fetch.c b/src/fetch.c
index a42732925..93f0980ca 100644
--- a/src/fetch.c
+++ b/src/fetch.c
@@ -24,7 +24,7 @@ static int filter_wants(git_remote *remote)
git_headarray refs;
git_remote_head *head;
git_transport *t = remote->transport;
- git_repository *repo = remote->repo;
+ git_odb *odb = NULL;
const git_refspec *spec;
int error;
unsigned int i = 0;
@@ -39,6 +39,10 @@ static int filter_wants(git_remote *remote)
goto cleanup;
}
+ error = git_repository_odb__weakptr(&odb, remote->repo);
+ if (error < GIT_SUCCESS)
+ goto cleanup;
+
/*
* The fetch refspec can be NULL, and what this means is that the
* user didn't specify one. This is fine, as it means that we're
@@ -53,7 +57,7 @@ static int filter_wants(git_remote *remote)
*/
head = refs.heads[0];
if (refs.len > 0 && !strcmp(head->name, GIT_HEAD_FILE)) {
- if (git_odb_exists(repo->db, &head->oid))
+ if (git_odb_exists(odb, &head->oid))
head->local = 1;
else
remote->need_pack = 1;
@@ -77,7 +81,7 @@ static int filter_wants(git_remote *remote)
}
/* If we have the object, mark it so we don't ask for it */
- if (git_odb_exists(repo->db, &head->oid))
+ if (git_odb_exists(odb, &head->oid))
head->local = 1;
else
remote->need_pack = 1;
diff --git a/src/index.c b/src/index.c
index aad117164..d01262b39 100644
--- a/src/index.c
+++ b/src/index.c
@@ -31,6 +31,8 @@ static const unsigned int INDEX_HEADER_SIG = 0x44495243;
static const char INDEX_EXT_TREECACHE_SIG[] = {'T', 'R', 'E', 'E'};
static const char INDEX_EXT_UNMERGED_SIG[] = {'R', 'E', 'U', 'C'};
+#define INDEX_OWNER(idx) ((git_repository *)(GIT_REFCOUNT_OWNER(idx)))
+
struct index_header {
uint32_t signature;
uint32_t version;
@@ -124,7 +126,7 @@ static unsigned int index_create_mode(unsigned int mode)
return S_IFREG | ((mode & 0100) ? 0755 : 0644);
}
-static int index_initialize(git_index **index_out, git_repository *owner, const char *index_path)
+int git_index_open(git_index **index_out, const char *index_path)
{
git_index *index;
@@ -142,8 +144,6 @@ static int index_initialize(git_index **index_out, git_repository *owner, const
return GIT_ENOMEM;
}
- index->repository = owner;
-
git_vector_init(&index->entries, 32, index_cmp);
/* Check if index file is stored on disk already */
@@ -151,23 +151,18 @@ static int index_initialize(git_index **index_out, git_repository *owner, const
index->on_disk = 1;
*index_out = index;
+ GIT_REFCOUNT_INC(index);
return git_index_read(index);
}
-int git_index_open(git_index **index_out, const char *index_path)
+static void index_free(git_index *index)
{
- return index_initialize(index_out, NULL, index_path);
-}
-
-/*
- * Moved from `repository.c`
- */
-int git_repository_index(git_index **index_out, git_repository *repo)
-{
- if (repo->is_bare)
- return git__throw(GIT_EBAREINDEX, "Failed to open index. Repository is bare");
+ git_index_clear(index);
+ git_vector_free(&index->entries);
+ git_vector_free(&index->unmerged);
- return index_initialize(index_out, repo, repo->path_index);
+ git__free(index->index_file_path);
+ git__free(index);
}
void git_index_free(git_index *index)
@@ -175,12 +170,7 @@ void git_index_free(git_index *index)
if (index == NULL)
return;
- git_index_clear(index);
- git_vector_free(&index->entries);
- git_vector_free(&index->unmerged);
-
- git__free(index->index_file_path);
- git__free(index);
+ GIT_REFCOUNT_DEC(index, index_free);
}
void git_index_clear(git_index *index)
@@ -298,20 +288,29 @@ static int index_entry_init(git_index_entry **entry_out, git_index *index, const
struct stat st;
git_oid oid;
int error;
+ const char *workdir;
+
+ if (INDEX_OWNER(index) == NULL)
+ return git__throw(GIT_EBAREINDEX,
+ "Failed to initialize entry. Repository is bare");
- if (index->repository == NULL)
- return git__throw(GIT_EBAREINDEX, "Failed to initialize entry. Repository is bare");
+ workdir = git_repository_workdir(INDEX_OWNER(index));
+ if (workdir == NULL)
+ return git__throw(GIT_EBAREINDEX,
+ "Failed to initialize entry. Cannot resolved workdir");
- git_path_join(full_path, index->repository->path_workdir, rel_path);
+ git_path_join(full_path, workdir, rel_path);
if (p_lstat(full_path, &st) < 0)
- return git__throw(GIT_ENOTFOUND, "Failed to initialize entry. '%s' cannot be opened", full_path);
+ return git__throw(GIT_ENOTFOUND,
+ "Failed to initialize entry. '%s' cannot be opened", full_path);
if (stage < 0 || stage > 3)
- return git__throw(GIT_ERROR, "Failed to initialize entry. Invalid stage %i", stage);
+ return git__throw(GIT_ERROR,
+ "Failed to initialize entry. Invalid stage %i", stage);
/* write the blob to disk and get the oid */
- if ((error = git_blob_create_fromfile(&oid, index->repository, rel_path)) < GIT_SUCCESS)
+ if ((error = git_blob_create_fromfile(&oid, INDEX_OWNER(index), rel_path)) < GIT_SUCCESS)
return git__rethrow(error, "Failed to initialize index entry");
entry = git__malloc(sizeof(git_index_entry));
diff --git a/src/index.h b/src/index.h
index a1cd3403e..9464afb6c 100644
--- a/src/index.h
+++ b/src/index.h
@@ -18,7 +18,8 @@
#define GIT_INDEX_FILE_MODE 0666
struct git_index {
- git_repository *repository;
+ git_refcount rc;
+
char *index_file_path;
time_t last_modified;
diff --git a/src/object.c b/src/object.c
index c84e94b05..12947f035 100644
--- a/src/object.c
+++ b/src/object.c
@@ -77,9 +77,15 @@ static int create_object(git_object **object_out, git_otype type)
return GIT_SUCCESS;
}
-int git_object_lookup_prefix(git_object **object_out, git_repository *repo, const git_oid *id, unsigned int len, git_otype type)
+int git_object_lookup_prefix(
+ git_object **object_out,
+ git_repository *repo,
+ const git_oid *id,
+ unsigned int len,
+ git_otype type)
{
git_object *object = NULL;
+ git_odb *odb = NULL;
git_odb_object *odb_obj;
int error = GIT_SUCCESS;
@@ -89,6 +95,10 @@ int git_object_lookup_prefix(git_object **object_out, git_repository *repo, cons
return git__throw(GIT_EAMBIGUOUSOIDPREFIX,
"Failed to lookup object. Prefix length is lower than %d.", GIT_OID_MINPREFIXLEN);
+ error = git_repository_odb__weakptr(&odb, repo);
+ if (error < GIT_SUCCESS)
+ return error;
+
if (len > GIT_OID_HEXSZ)
len = GIT_OID_HEXSZ;
@@ -98,10 +108,11 @@ int git_object_lookup_prefix(git_object **object_out, git_repository *repo, cons
*/
object = git_cache_get(&repo->objects, id);
if (object != NULL) {
- if (type != GIT_OBJ_ANY && type != object->type)
- {
+ if (type != GIT_OBJ_ANY && type != object->type) {
git_object_close(object);
- return git__throw(GIT_EINVALIDTYPE, "Failed to lookup object. The given type does not match the type on the ODB");
+ return git__throw(GIT_EINVALIDTYPE,
+ "Failed to lookup object. "
+ "The given type does not match the type on the ODB");
}
*object_out = object;
@@ -113,7 +124,7 @@ int git_object_lookup_prefix(git_object **object_out, git_repository *repo, cons
* it is the same cost for packed and loose object backends,
* but it may be much more costly for sqlite and hiredis.
*/
- error = git_odb_read(&odb_obj, repo->db, id);
+ error = git_odb_read(&odb_obj, odb, id);
} else {
git_oid short_oid;
@@ -133,7 +144,7 @@ int git_object_lookup_prefix(git_object **object_out, git_repository *repo, cons
* - We never explore the cache, go right to exploring the backends
* We chose the latter : we explore directly the backends.
*/
- error = git_odb_read_prefix(&odb_obj, repo->db, &short_oid, len);
+ error = git_odb_read_prefix(&odb_obj, odb, &short_oid, len);
}
if (error < GIT_SUCCESS)
diff --git a/src/odb.c b/src/odb.c
index 69fdba009..9b72e7fd3 100644
--- a/src/odb.c
+++ b/src/odb.c
@@ -275,6 +275,7 @@ int git_odb_new(git_odb **out)
}
*out = db;
+ GIT_REFCOUNT_INC(db);
return GIT_SUCCESS;
}
@@ -405,17 +406,14 @@ int git_odb_open(git_odb **out, const char *objects_dir)
return GIT_SUCCESS;
cleanup:
- git_odb_close(db);
+ git_odb_free(db);
return error; /* error already set - pass through */
}
-void git_odb_close(git_odb *db)
+static void odb_free(git_odb *db)
{
unsigned int i;
- if (db == NULL)
- return;
-
for (i = 0; i < db->backends.length; ++i) {
backend_internal *internal = git_vector_get(&db->backends, i);
git_odb_backend *backend = internal->backend;
@@ -431,6 +429,14 @@ void git_odb_close(git_odb *db)
git__free(db);
}
+void git_odb_free(git_odb *db)
+{
+ if (db == NULL)
+ return;
+
+ GIT_REFCOUNT_DEC(db, odb_free);
+}
+
int git_odb_exists(git_odb *db, const git_oid *id)
{
git_odb_object *object;
diff --git a/src/odb.h b/src/odb.h
index 833739e99..b81533001 100644
--- a/src/odb.h
+++ b/src/odb.h
@@ -33,7 +33,7 @@ struct git_odb_object {
/* EXPORT */
struct git_odb {
- void *_internal;
+ git_refcount rc;
git_vector backends;
git_cache cache;
};
diff --git a/src/refs.c b/src/refs.c
index 2374cc72f..4c45fec2c 100644
--- a/src/refs.c
+++ b/src/refs.c
@@ -1195,7 +1195,8 @@ cleanup:
*/
int git_reference_set_oid(git_reference *ref, const git_oid *id)
{
- int error = GIT_SUCCESS;
+ int error = GIT_SUCCESS, exists;
+ git_odb *odb = NULL;
if ((ref->flags & GIT_REF_OID) == 0)
return git__throw(GIT_EINVALIDREFSTATE,
@@ -1203,23 +1204,29 @@ int git_reference_set_oid(git_reference *ref, const git_oid *id)
assert(ref->owner);
+ error = git_repository_odb__weakptr(&odb, ref->owner);
+ if (error < GIT_SUCCESS)
+ return error;
+
+ exists = git_odb_exists(odb, id);
+
+ git_odb_free(odb);
+
/* Don't let the user create references to OIDs that
* don't exist in the ODB */
- if (!git_odb_exists(git_repository_database(ref->owner), id))
+ if (!exists)
return git__throw(GIT_ENOTFOUND,
"Failed to set OID target of reference. OID doesn't exist in ODB");
/* Update the OID value on `ref` */
git_oid_cpy(&ref->target.oid, id);
+ /* Write back to disk */
error = loose_write(ref);
if (error < GIT_SUCCESS)
- goto cleanup;
+ return git__rethrow(error, "Failed to set OID target of reference");
return GIT_SUCCESS;
-
-cleanup:
- return git__rethrow(error, "Failed to set OID target of reference");
}
/*
diff --git a/src/remote.c b/src/remote.c
index a222023d8..c6a9173af 100644
--- a/src/remote.c
+++ b/src/remote.c
@@ -88,14 +88,19 @@ int git_remote_new(git_remote **out, git_repository *repo, const char *url, cons
return GIT_SUCCESS;
}
-int git_remote_get(git_remote **out, git_config *cfg, const char *name)
+int git_remote_load(git_remote **out, git_repository *repo, const char *name)
{
git_remote *remote;
char *buf = NULL;
const char *val;
int ret, error, buf_len;
+ git_config *config;
- assert(out && cfg && name);
+ assert(out && repo && name);
+
+ error = git_repository_config__weakptr(&config, repo);
+ if (error < GIT_SUCCESS)
+ return error;
remote = git__malloc(sizeof(git_remote));
if (remote == NULL)
@@ -122,13 +127,13 @@ int git_remote_get(git_remote **out, git_config *cfg, const char *name)
goto cleanup;
}
- error = git_config_get_string(cfg, buf, &val);
+ error = git_config_get_string(config, buf, &val);
if (error < GIT_SUCCESS) {
error = git__rethrow(error, "Remote's url doesn't exist");
goto cleanup;
}
- remote->repo = cfg->repo;
+ remote->repo = repo;
remote->url = git__strdup(val);
if (remote->url == NULL) {
error = GIT_ENOMEM;
@@ -141,7 +146,7 @@ int git_remote_get(git_remote **out, git_config *cfg, const char *name)
goto cleanup;
}
- error = parse_remote_refspec(cfg, &remote->fetch, buf);
+ error = parse_remote_refspec(config, &remote->fetch, buf);
if (error < GIT_SUCCESS) {
error = git__rethrow(error, "Failed to get fetch refspec");
goto cleanup;
@@ -153,7 +158,7 @@ int git_remote_get(git_remote **out, git_config *cfg, const char *name)
goto cleanup;
}
- error = parse_remote_refspec(cfg, &remote->push, buf);
+ error = parse_remote_refspec(config, &remote->push, buf);
/* Not finding push is fine */
if (error == GIT_ENOTFOUND)
error = GIT_SUCCESS;
@@ -165,6 +170,7 @@ int git_remote_get(git_remote **out, git_config *cfg, const char *name)
cleanup:
git__free(buf);
+
if (error < GIT_SUCCESS)
git_remote_free(remote);
diff --git a/src/repository.c b/src/repository.c
index f8195e2d9..7bac1b271 100644
--- a/src/repository.c
+++ b/src/repository.c
@@ -24,118 +24,57 @@
#define GIT_BRANCH_MASTER "master"
-/*
- * Git repository open methods
- *
- * Open a repository object from its path
- */
-static int assign_repository_dirs(
- git_repository *repo,
- const char *git_dir,
- const char *git_object_directory,
- const char *git_index_file,
- const char *git_work_tree)
-{
- char path_aux[GIT_PATH_MAX];
- int error = GIT_SUCCESS;
-
- assert(repo);
-
- if (git_dir == NULL)
- return git__throw(GIT_ENOTFOUND, "Failed to open repository. Git dir not found");
- error = git_path_prettify_dir(path_aux, git_dir, NULL);
- if (error < GIT_SUCCESS)
- return git__rethrow(error, "Failed to open repository");
-
- /* store GIT_DIR */
- repo->path_repository = git__strdup(path_aux);
- if (repo->path_repository == NULL)
- return GIT_ENOMEM;
-
- /* path to GIT_OBJECT_DIRECTORY */
- if (git_object_directory == NULL)
- git_path_join(path_aux, repo->path_repository, GIT_OBJECTS_DIR);
- else {
- error = git_path_prettify_dir(path_aux, git_object_directory, NULL);
- if (error < GIT_SUCCESS)
- return git__rethrow(error, "Failed to open repository");
+static void drop_odb(git_repository *repo)
+{
+ if (repo->_odb != NULL) {
+ GIT_REFCOUNT_OWN(repo->_odb, NULL);
+ git_odb_free(repo->_odb);
+ repo->_odb = NULL;
}
+}
- /* Store GIT_OBJECT_DIRECTORY */
- repo->path_odb = git__strdup(path_aux);
- if (repo->path_odb == NULL)
- return GIT_ENOMEM;
-
- /* path to GIT_WORK_TREE */
- if (git_work_tree == NULL)
- repo->is_bare = 1;
- else {
- error = git_path_prettify_dir(path_aux, git_work_tree, NULL);
- if (error < GIT_SUCCESS)
- return git__rethrow(error, "Failed to open repository");
-
- /* Store GIT_WORK_TREE */
- repo->path_workdir = git__strdup(path_aux);
- if (repo->path_workdir == NULL)
- return GIT_ENOMEM;
-
- /* Path to GIT_INDEX_FILE */
- if (git_index_file == NULL)
- git_path_join(path_aux, repo->path_repository, GIT_INDEX_FILE);
- else {
- error = git_path_prettify(path_aux, git_index_file, NULL);
- if (error < GIT_SUCCESS)
- return git__rethrow(error, "Failed to open repository");
- }
-
- /* store GIT_INDEX_FILE */
- repo->path_index = git__strdup(path_aux);
- if (repo->path_index == NULL)
- return GIT_ENOMEM;
+static void drop_config(git_repository *repo)
+{
+ if (repo->_config != NULL) {
+ GIT_REFCOUNT_OWN(repo->_config, NULL);
+ git_config_free(repo->_config);
+ repo->_config = NULL;
}
-
- return GIT_SUCCESS;
}
-static int check_repository_dirs(git_repository *repo)
+static void drop_index(git_repository *repo)
{
- char path_aux[GIT_PATH_MAX];
-
- if (git_futils_isdir(repo->path_repository) < GIT_SUCCESS)
- return git__throw(GIT_ENOTAREPO, "`%s` is not a folder", repo->path_repository);
-
- /* Ensure GIT_OBJECT_DIRECTORY exists */
- if (git_futils_isdir(repo->path_odb) < GIT_SUCCESS)
- return git__throw(GIT_ENOTAREPO, "`%s` does not exist", repo->path_odb);
-
- /* Ensure HEAD file exists */
- git_path_join(path_aux, repo->path_repository, GIT_HEAD_FILE);
- if (git_futils_isfile(path_aux) < 0)
- return git__throw(GIT_ENOTAREPO, "HEAD file is missing");
-
- return GIT_SUCCESS;
+ if (repo->_index != NULL) {
+ GIT_REFCOUNT_OWN(repo->_index, NULL);
+ git_index_free(repo->_index);
+ repo->_index = NULL;
+ }
}
-static int guess_repository_dirs(git_repository *repo, const char *repository_path)
+void git_repository_free(git_repository *repo)
{
- char buffer[GIT_PATH_MAX];
- const char *path_work_tree = NULL;
+ if (repo == NULL)
+ return;
- /* Git directory name */
- if (git_path_basename_r(buffer, sizeof(buffer), repository_path) < 0)
- return git__throw(GIT_EINVALIDPATH, "Unable to parse folder name from `%s`", repository_path);
+ git_cache_free(&repo->objects);
+ git_repository__refcache_free(&repo->references);
- if (strcmp(buffer, DOT_GIT) == 0) {
- /* Path to working dir */
- if (git_path_dirname_r(buffer, sizeof(buffer), repository_path) < 0)
- return git__throw(GIT_EINVALIDPATH, "Unable to parse parent folder name from `%s`", repository_path);
- path_work_tree = buffer;
- }
+ git__free(repo->path_repository);
+ git__free(repo->workdir);
- return assign_repository_dirs(repo, repository_path, NULL, NULL, path_work_tree);
+ drop_config(repo);
+ drop_index(repo);
+ drop_odb(repo);
+
+ git__free(repo);
}
+/*
+ * Git repository open methods
+ *
+ * Open a repository object from its path
+ */
static int quickcheck_repository_dir(const char *repository_path)
{
char path_aux[GIT_PATH_MAX];
@@ -156,6 +95,7 @@ static int quickcheck_repository_dir(const char *repository_path)
return GIT_SUCCESS;
}
+
static git_repository *repository_alloc(void)
{
int error;
@@ -175,94 +115,95 @@ static git_repository *repository_alloc(void)
return repo;
}
-static int init_odb(git_repository *repo)
+static int load_config_data(git_repository *repo)
{
- return git_odb_open(&repo->db, repo->path_odb);
-}
+ int error, is_bare;
+ git_config *config;
-int git_repository_open3(git_repository **repo_out,
- const char *git_dir,
- git_odb *object_database,
- const char *git_index_file,
- const char *git_work_tree)
-{
- git_repository *repo;
- int error = GIT_SUCCESS;
-
- assert(repo_out);
+ error = git_repository_config__weakptr(&config, repo);
+ if (error < GIT_SUCCESS)
+ return error;
- if (object_database == NULL)
- return git__throw(GIT_EINVALIDARGS, "Failed to open repository. `object_database` can't be null");
+ error = git_config_get_bool(config, "core.bare", &is_bare);
+ if (error == GIT_SUCCESS)
+ repo->is_bare = is_bare;
- repo = repository_alloc();
- if (repo == NULL)
- return GIT_ENOMEM;
+ return GIT_SUCCESS;
+}
- error = assign_repository_dirs(repo,
- git_dir,
- NULL,
- git_index_file,
- git_work_tree);
+static int load_workdir(git_repository *repo)
+{
+ if (!repo->is_bare) {
+ char workdir_buf[GIT_PATH_MAX];
- if (error < GIT_SUCCESS)
- goto cleanup;
+ if (git_path_dirname_r(workdir_buf, sizeof(workdir_buf), repo->path_repository) < 0)
+ return git__throw(GIT_EOSERR,
+ "Failed to resolved working directory");
- error = check_repository_dirs(repo);
- if (error < GIT_SUCCESS)
- goto cleanup;
+ git_path_join(workdir_buf, workdir_buf, "");
- repo->db = object_database;
+ repo->workdir = git__strdup(workdir_buf);
+ if (repo->workdir == NULL)
+ return GIT_ENOMEM;
+ }
- *repo_out = repo;
return GIT_SUCCESS;
-
-cleanup:
- git_repository_free(repo);
- return git__rethrow(error, "Failed to open repository");
}
-
-int git_repository_open2(git_repository **repo_out,
- const char *git_dir,
- const char *git_object_directory,
- const char *git_index_file,
- const char *git_work_tree)
+int git_repository_open(git_repository **repo_out, const char *path)
{
- git_repository *repo;
int error = GIT_SUCCESS;
+ char path_buf[GIT_PATH_MAX];
+ size_t path_len;
+ git_repository *repo = NULL;
+
+ error = git_path_prettify_dir(path_buf, path, NULL);
+ if (error < GIT_SUCCESS)
+ return git__rethrow(error, "Failed to open repository");
- assert(repo_out);
+ path_len = strlen(path_buf);
+
+ /**
+ * Check if the path we've been given is actually the path
+ * of the working dir, by testing if it contains a `.git`
+ * folder inside of it.
+ */
+ git_path_join(path_buf, path_buf, DOT_GIT);
+ if (git_futils_isdir(path_buf) < GIT_SUCCESS) {
+ path_buf[path_len] = 0;
+ }
+
+ if (quickcheck_repository_dir(path_buf) < GIT_SUCCESS)
+ return git__throw(GIT_ENOTAREPO,
+ "The given path is not a valid Git repository");
repo = repository_alloc();
if (repo == NULL)
return GIT_ENOMEM;
- error = assign_repository_dirs(repo,
- git_dir,
- git_object_directory,
- git_index_file,
- git_work_tree);
-
- if (error < GIT_SUCCESS)
- goto cleanup;
+ repo->path_repository = git__strdup(path_buf);
+ if (repo->path_repository == NULL) {
+ git_repository_free(repo);
+ return GIT_ENOMEM;
+ }
- error = check_repository_dirs(repo);
- if (error < GIT_SUCCESS)
- goto cleanup;
+ error = load_config_data(repo);
+ if (error < GIT_SUCCESS) {
+ git_repository_free(repo);
+ return error;
+ }
- error = init_odb(repo);
- if (error < GIT_SUCCESS)
- goto cleanup;
+ error = load_workdir(repo);
+ if (error < GIT_SUCCESS) {
+ git_repository_free(repo);
+ return error;
+ }
*repo_out = repo;
return GIT_SUCCESS;
-
-cleanup:
- git_repository_free(repo);
- return git__rethrow(error, "Failed to open repository");
}
-int git_repository_config(
+static int load_config(
git_config **out,
git_repository *repo,
const char *global_config_path,
@@ -270,98 +211,178 @@ int git_repository_config(
{
char config_path[GIT_PATH_MAX];
int error;
+ git_config *cfg = NULL;
- assert(out && repo);
+ assert(repo && out);
- error = git_config_new(out);
+ error = git_config_new(&cfg);
if (error < GIT_SUCCESS)
return error;
git_path_join(config_path, repo->path_repository, GIT_CONFIG_FILENAME_INREPO);
- error = git_config_add_file_ondisk(*out, config_path, 3);
+ error = git_config_add_file_ondisk(cfg, config_path, 3);
if (error < GIT_SUCCESS)
goto cleanup;
if (global_config_path != NULL) {
- error = git_config_add_file_ondisk(*out, global_config_path, 2);
+ error = git_config_add_file_ondisk(cfg, global_config_path, 2);
if (error < GIT_SUCCESS)
goto cleanup;
}
if (system_config_path != NULL) {
- error = git_config_add_file_ondisk(*out, system_config_path, 1);
+ error = git_config_add_file_ondisk(cfg, system_config_path, 1);
if (error < GIT_SUCCESS)
goto cleanup;
}
- (*out)->repo = repo;
+ *out = cfg;
return GIT_SUCCESS;
cleanup:
- git_config_free(*out);
+ git_config_free(cfg);
+ *out = NULL;
return error;
}
-int git_repository_config_autoload(
- git_config **out,
- git_repository *repo)
+int git_repository_config__weakptr(git_config **out, git_repository *repo)
{
- char global[GIT_PATH_MAX], system[GIT_PATH_MAX];
- char *global_path, *system_path;
- int error;
+ if (repo->_config == NULL) {
+ int error;
+
+ char buf_global[GIT_PATH_MAX], buf_system[GIT_PATH_MAX];
+
+ const char *global_config_path = NULL;
+ const char *system_config_path = NULL;
+ if (git_config_find_global(buf_global) == GIT_SUCCESS)
+ global_config_path = buf_global;
- error = git_config_find_global(global);
- global_path = error < GIT_SUCCESS ? NULL : global;
+ if (git_config_find_system(buf_system) == GIT_SUCCESS)
+ system_config_path = buf_system;
- error = git_config_find_system(system);
- system_path = error < GIT_SUCCESS ? NULL : system;
+ error = load_config(&repo->_config, repo, global_config_path, system_config_path);
+ if (error < GIT_SUCCESS)
+ return error;
+
+ GIT_REFCOUNT_OWN(repo->_config, repo);
+ }
- return git_repository_config(out, repo, global_path, system_path);
+ *out = repo->_config;
+ return GIT_SUCCESS;
}
-static int discover_repository_dirs(git_repository *repo, const char *path)
+int git_repository_config(git_config **out, git_repository *repo)
{
- int error;
+ int error = git_repository_config__weakptr(out, repo);
- error = guess_repository_dirs(repo, path);
- if (error < GIT_SUCCESS)
- return error;
+ if (error == GIT_SUCCESS) {
+ GIT_REFCOUNT_INC(*out);
+ }
- error = check_repository_dirs(repo);
- if (error < GIT_SUCCESS)
- return error;
+ return error;
+}
+
+void git_repository_set_config(git_repository *repo, git_config *config)
+{
+ assert(repo && config);
+
+ drop_config(repo);
+
+ repo->_config = config;
+ GIT_REFCOUNT_OWN(repo->_config, repo);
+}
+
+int git_repository_odb__weakptr(git_odb **out, git_repository *repo)
+{
+ assert(repo && out);
+
+ if (repo->_odb == NULL) {
+ int error;
+ char odb_path[GIT_PATH_MAX];
+
+ git_path_join(odb_path, repo->path_repository, GIT_OBJECTS_DIR);
+
+ error = git_odb_open(&repo->_odb, odb_path);
+ if (error < GIT_SUCCESS)
+ return error;
+
+ GIT_REFCOUNT_OWN(repo->_odb, repo);
+ }
+ GIT_REFCOUNT_INC(repo->_odb);
+ *out = repo->_odb;
return GIT_SUCCESS;
}
-int git_repository_open(git_repository **repo_out, const char *path)
+int git_repository_odb(git_odb **out, git_repository *repo)
{
- git_repository *repo;
- int error = GIT_SUCCESS;
+ int error = git_repository_odb__weakptr(out, repo);
- assert(repo_out && path);
+ if (error == GIT_SUCCESS) {
+ GIT_REFCOUNT_INC(*out);
+ }
- repo = repository_alloc();
- if (repo == NULL)
- return GIT_ENOMEM;
+ return error;
+}
- error = discover_repository_dirs(repo, path);
- if (error < GIT_SUCCESS)
- goto cleanup;
+void git_repository_set_odb(git_repository *repo, git_odb *odb)
+{
+ assert(repo && odb);
- error = init_odb(repo);
- if (error < GIT_SUCCESS)
- goto cleanup;
+ drop_odb(repo);
- *repo_out = repo;
+ repo->_odb = odb;
+ GIT_REFCOUNT_OWN(repo->_odb, repo);
+}
+
+int git_repository_index__weakptr(git_index **out, git_repository *repo)
+{
+ assert(out && repo);
+
+ if (repo->is_bare)
+ return git__throw(GIT_EBAREINDEX, "Cannot open index in bare repository");
+
+ if (repo->_index == NULL) {
+ int error;
+ char index_path[GIT_PATH_MAX];
+
+ git_path_join(index_path, repo->path_repository, GIT_INDEX_FILE);
+
+ error = git_index_open(&repo->_index, index_path);
+ if (error < GIT_SUCCESS)
+ return error;
+
+ GIT_REFCOUNT_OWN(repo->_index, repo);
+ }
+
+ GIT_REFCOUNT_INC(repo->_index);
+ *out = repo->_index;
return GIT_SUCCESS;
+}
-cleanup:
- git_repository_free(repo);
- return git__rethrow(error, "Failed to open repository");
+int git_repository_index(git_index **out, git_repository *repo)
+{
+ int error = git_repository_index__weakptr(out, repo);
+
+ if (error == GIT_SUCCESS) {
+ GIT_REFCOUNT_INC(*out);
+ }
+
+ return error;
}
+void git_repository_set_index(git_repository *repo, git_index *index)
+{
+ assert(repo && index);
+
+ drop_index(repo);
+
+ repo->_index = index;
+ GIT_REFCOUNT_OWN(repo->_index, repo);
+}
+
+
static int retrieve_device(dev_t *device_out, const char *path)
{
struct stat path_info;
@@ -460,34 +481,12 @@ static int read_gitfile(char *path_out, const char *file_path, const char *base_
return git__throw(GIT_EOBJCORRUPTED, "The `.git` file points to an inexisting path");
}
-static void git_repository__free_dirs(git_repository *repo)
-{
- git__free(repo->path_workdir);
- repo->path_workdir = NULL;
- git__free(repo->path_index);
- repo->path_index = NULL;
- git__free(repo->path_repository);
- repo->path_repository = NULL;
- git__free(repo->path_odb);
- repo->path_odb = NULL;
-}
-
-void git_repository_free(git_repository *repo)
-{
- if (repo == NULL)
- return;
-
- git_cache_free(&repo->objects);
- git_repository__refcache_free(&repo->references);
- git_repository__free_dirs(repo);
-
- if (repo->db != NULL)
- git_odb_close(repo->db);
-
- git__free(repo);
-}
-
-int git_repository_discover(char *repository_path, size_t size, const char *start_path, int across_fs, const char *ceiling_dirs)
+int git_repository_discover(
+ char *repository_path,
+ size_t size,
+ const char *start_path,
+ int across_fs,
+ const char *ceiling_dirs)
{
int error, ceiling_offset;
char bare_path[GIT_PATH_MAX];
@@ -519,11 +518,13 @@ int git_repository_discover(char *repository_path, size_t size, const char *star
error = read_gitfile(repository_path, normal_path, bare_path);
if (error < GIT_SUCCESS)
- return git__rethrow(error, "Unable to read git file `%s`", normal_path);
+ return git__rethrow(error,
+ "Unable to read git file `%s`", normal_path);
error = quickcheck_repository_dir(repository_path);
if (error < GIT_SUCCESS)
- return git__throw(GIT_ENOTFOUND, "The `.git` file found at '%s' points"
+ return git__throw(GIT_ENOTFOUND,
+ "The `.git` file found at '%s' points"
"to an inexisting Git folder", normal_path);
return GIT_SUCCESS;
@@ -558,7 +559,8 @@ int git_repository_discover(char *repository_path, size_t size, const char *star
error = retrieve_device(&new_device, normal_path);
if (error < GIT_SUCCESS || current_device != new_device) {
- return git__throw(GIT_ENOTAREPO,"Not a git repository (or any parent up to mount parent %s)\n"
+ return git__throw(GIT_ENOTAREPO,
+ "Not a git repository (or any parent up to mount parent %s)\n"
"Stopping at filesystem boundary.", bare_path);
}
current_device = new_device;
@@ -569,43 +571,81 @@ int git_repository_discover(char *repository_path, size_t size, const char *star
// nothing has been found, lets try the parent directory
if (bare_path[ceiling_offset] == '\0') {
- return git__throw(GIT_ENOTAREPO,"Not a git repository (or any of the parent directories): %s", start_path);
+ return git__throw(GIT_ENOTAREPO,
+ "Not a git repository (or any of the parent directories): %s", start_path);
}
}
if (size < strlen(found_path) + 2) {
- return git__throw(GIT_ESHORTBUFFER, "The repository buffer is not long enough to handle the repository path `%s`", found_path);
+ return git__throw(GIT_ESHORTBUFFER,
+ "The repository buffer is not long enough to handle the repository path `%s`", found_path);
}
git_path_join(repository_path, found_path, "");
return GIT_SUCCESS;
}
-git_odb *git_repository_database(git_repository *repo)
-{
- assert(repo);
- return repo->db;
-}
-
static int repo_init_reinit(const char *repository_path, int is_bare)
{
/* TODO: reinit the repository */
return git__throw(GIT_ENOTIMPLEMENTED,
"Failed to reinitialize the %srepository at '%s'. "
"This feature is not yet implemented",
- is_bare ? "bare" : "", repository_path);
+ is_bare ? "bare " : "", repository_path);
}
-static int repo_init_createhead(git_repository *repo)
+static int repo_init_createhead(const char *git_dir)
{
- int error;
- git_reference *head_reference;
+ char ref_path[GIT_PATH_MAX];
+ git_filebuf ref = GIT_FILEBUF_INIT;
+
+ git_path_join(ref_path, git_dir, GIT_HEAD_FILE);
+
+ git_filebuf_open(&ref, ref_path, 0);
+ git_filebuf_printf(&ref, "ref: refs/heads/master\n");
+
+ return git_filebuf_commit(&ref, GIT_REFS_FILE_MODE);
+}
+
+static int repo_init_config(const char *git_dir, int is_bare)
+{
+ char cfg_path[GIT_PATH_MAX];
+ git_filebuf cfg = GIT_FILEBUF_INIT;
+
+ git_path_join(cfg_path, git_dir, GIT_CONFIG_FILENAME_INREPO);
- error = git_reference_create_symbolic(&head_reference, repo, GIT_HEAD_FILE, GIT_REFS_HEADS_MASTER_FILE, 0);
+ git_filebuf_open(&cfg, cfg_path, 0);
+ git_filebuf_printf(&cfg, "[core]\n");
+ git_filebuf_printf(&cfg, "\tbare = %s\n", is_bare ? "true" : "false");
+ git_filebuf_printf(&cfg, "\trepositoryformatversion = 0\n");
- git_reference_free(head_reference);
+ return git_filebuf_commit(&cfg, GIT_REFS_FILE_MODE);
+ /* TODO: use the config backend to write this */
+#if 0
+ git_config *config;
+ int error = GIT_SUCCESS;
+
+#define SET_REPO_CONFIG(type, name, val) {\
+ error = git_config_set_##type(config, name, val);\
+ if (error < GIT_SUCCESS)\
+ goto cleanup;\
+}
+
+ git_path_join(cfg_path, git_dir, GIT_CONFIG_FILENAME_INREPO);
+
+ error = git_config_open_ondisk(&config, cfg_path);
+ if (error < GIT_SUCCESS)
+ return error;
+
+ SET_REPO_CONFIG(bool, "core.bare", is_bare);
+ SET_REPO_CONFIG(int32, "core.repositoryformatversion", 0);
+ /* TODO: what other defaults? */
+
+cleanup:
+ git_config_free(config);
return error;
+#endif
}
static int repo_init_structure(const char *git_dir, int is_bare)
@@ -674,31 +714,15 @@ int git_repository_init(git_repository **repo_out, const char *path, unsigned is
if (error < GIT_SUCCESS)
goto cleanup;
- repo = repository_alloc();
- if (repo == NULL) {
- error = GIT_ENOMEM;
- goto cleanup;
- }
-
- error = guess_repository_dirs(repo, repository_path);
+ error = repo_init_config(repository_path, is_bare);
if (error < GIT_SUCCESS)
goto cleanup;
- assert(repo->is_bare == is_bare);
-
- error = init_odb(repo);
- if (error < GIT_SUCCESS)
- goto cleanup;
-
- error = repo_init_createhead(repo);
+ error = repo_init_createhead(repository_path);
if (error < GIT_SUCCESS)
goto cleanup;
- /* should never fail */
- assert(check_repository_dirs(repo) == GIT_SUCCESS);
-
- *repo_out = repo;
- return GIT_SUCCESS;
+ return git_repository_open(repo_out, repository_path);
cleanup:
git_repository_free(repo);
@@ -709,8 +733,13 @@ int git_repository_head_detached(git_repository *repo)
{
git_reference *ref;
int error;
- size_t GIT_UNUSED(_size);
+ size_t _size;
git_otype type;
+ git_odb *odb = NULL;
+
+ error = git_repository_odb__weakptr(&odb, repo);
+ if (error < GIT_SUCCESS)
+ return error;
error = git_reference_lookup(&ref, repo, GIT_HEAD_FILE);
if (error < GIT_SUCCESS)
@@ -721,7 +750,7 @@ int git_repository_head_detached(git_repository *repo)
return 0;
}
- error = git_odb_read_header(&_size, &type, repo->db, git_reference_oid(ref));
+ error = git_odb_read_header(&_size, &type, odb, git_reference_oid(ref));
git_reference_free(ref);
@@ -797,26 +826,34 @@ int git_repository_is_empty(git_repository *repo)
return error == GIT_ENOTFOUND ? 1 : error;
}
-const char *git_repository_path(git_repository *repo, git_repository_pathid id)
+const char *git_repository_path(git_repository *repo)
{
assert(repo);
+ return repo->path_repository;
+}
- switch (id) {
- case GIT_REPO_PATH:
- return repo->path_repository;
+const char *git_repository_workdir(git_repository *repo)
+{
+ assert(repo);
- case GIT_REPO_PATH_INDEX:
- return repo->path_index;
+ if (repo->is_bare)
+ return NULL;
- case GIT_REPO_PATH_ODB:
- return repo->path_odb;
+ return repo->workdir;
+}
- case GIT_REPO_PATH_WORKDIR:
- return repo->path_workdir;
+int git_repository_set_workdir(git_repository *repo, const char *workdir)
+{
+ assert(repo && workdir);
- default:
- return NULL;
- }
+ free(repo->workdir);
+
+ repo->workdir = git__strdup(workdir);
+ if (repo->workdir == NULL)
+ return GIT_ENOMEM;
+
+ repo->is_bare = 0;
+ return GIT_SUCCESS;
}
int git_repository_is_bare(git_repository *repo)
diff --git a/src/repository.h b/src/repository.h
index 0c17958fd..c3a9a5c60 100644
--- a/src/repository.h
+++ b/src/repository.h
@@ -32,15 +32,15 @@ struct git_object {
};
struct git_repository {
- git_odb *db;
+ git_odb *_odb;
+ git_config *_config;
+ git_index *_index;
git_cache objects;
git_refcache references;
char *path_repository;
- char *path_index;
- char *path_odb;
- char *path_workdir;
+ char *workdir;
unsigned is_bare:1;
unsigned int lru_counter;
@@ -53,4 +53,8 @@ void git_object__free(void *object);
int git_oid__parse(git_oid *oid, const char **buffer_out, const char *buffer_end, const char *header);
void git_oid__writebuf(git_buf *buf, const char *header, const git_oid *oid);
+int git_repository_config__weakptr(git_config **out, git_repository *repo);
+int git_repository_odb__weakptr(git_odb **out, git_repository *repo);
+int git_repository_index__weakptr(git_index **out, git_repository *repo);
+
#endif
diff --git a/src/revwalk.c b/src/revwalk.c
index 7e31650ff..64775649c 100644
--- a/src/revwalk.c
+++ b/src/revwalk.c
@@ -34,6 +34,7 @@ typedef struct commit_list {
struct git_revwalk {
git_repository *repo;
+ git_odb *odb;
git_hashtable *commits;
@@ -225,7 +226,7 @@ static int commit_parse(git_revwalk *walk, commit_object *commit)
if (commit->parsed)
return GIT_SUCCESS;
- if ((error = git_odb_read(&obj, walk->repo->db, &commit->oid)) < GIT_SUCCESS)
+ if ((error = git_odb_read(&obj, walk->odb, &commit->oid)) < GIT_SUCCESS)
return git__rethrow(error, "Failed to parse commit. Can't read object");
if (obj->raw.type != GIT_OBJ_COMMIT) {
@@ -429,6 +430,7 @@ static int prepare_walk(git_revwalk *walk)
int git_revwalk_new(git_revwalk **revwalk_out, git_repository *repo)
{
+ int error;
git_revwalk *walk;
walk = git__malloc(sizeof(git_revwalk));
@@ -455,6 +457,12 @@ int git_revwalk_new(git_revwalk **revwalk_out, git_repository *repo)
walk->repo = repo;
+ error = git_repository_odb(&walk->odb, repo);
+ if (error < GIT_SUCCESS) {
+ git_revwalk_free(walk);
+ return error;
+ }
+
*revwalk_out = walk;
return GIT_SUCCESS;
}
@@ -469,6 +477,7 @@ void git_revwalk_free(git_revwalk *walk)
return;
git_revwalk_reset(walk);
+ git_odb_free(walk->odb);
/* if the parent has more than PARENTS_PER_COMMIT parents,
* we had to allocate a separate array for those parents.
diff --git a/src/status.c b/src/status.c
index d50199d9a..d09abfd69 100644
--- a/src/status.c
+++ b/src/status.c
@@ -410,9 +410,15 @@ int git_status_foreach(git_repository *repo, int (*callback)(const char *, unsig
unsigned int i;
git_tree *tree;
struct status_entry *e;
+ const char *workdir;
- if ((error = git_repository_index(&index, repo)) < GIT_SUCCESS) {
- return git__rethrow(error, "Failed to determine statuses. Index can't be opened");
+ if ((workdir = git_repository_workdir(repo)) == NULL)
+ return git__throw(GIT_ERROR,
+ "Cannot retrieve status on a bare repository");
+
+ if ((error = git_repository_index__weakptr(&index, repo)) < GIT_SUCCESS) {
+ return git__rethrow(error,
+ "Failed to determine statuses. Index can't be opened");
}
if ((error = retrieve_head_tree(&tree, repo)) < GIT_SUCCESS) {
@@ -422,7 +428,7 @@ int git_status_foreach(git_repository *repo, int (*callback)(const char *, unsig
git_vector_init(&entries, DEFAULT_SIZE, status_cmp);
- dirent_st.workdir_path_len = strlen(repo->path_workdir);
+ dirent_st.workdir_path_len = strlen(workdir);
dirent_st.tree_position = 0;
dirent_st.index_position = 0;
dirent_st.tree = tree;
@@ -432,18 +438,29 @@ int git_status_foreach(git_repository *repo, int (*callback)(const char *, unsig
dirent_st.head_tree_relative_path_len = 0;
dirent_st.is_dir = 1;
- strcpy(temp_path, repo->path_workdir);
+ strcpy(temp_path, workdir);
if (git_futils_isdir(temp_path)) {
- error = git__throw(GIT_EINVALIDPATH, "Failed to determine status of file '%s'. Provided path doesn't lead to a folder", temp_path);
+ error = git__throw(GIT_EINVALIDPATH,
+ "Failed to determine status of file '%s'. "
+ "The given path doesn't lead to a folder", temp_path);
goto exit;
}
- if ((error = alphasorted_futils_direach(temp_path, sizeof(temp_path), dirent_cb, &dirent_st)) < GIT_SUCCESS)
- error = git__rethrow(error, "Failed to determine statuses. An error occured while processing the working directory");
+ error = alphasorted_futils_direach(
+ temp_path, sizeof(temp_path),
+ dirent_cb, &dirent_st
+ );
+
+ if (error < GIT_SUCCESS)
+ error = git__rethrow(error,
+ "Failed to determine statuses. "
+ "An error occured while processing the working directory");
if ((error == GIT_SUCCESS) && ((error = dirent_cb(&dirent_st, NULL)) < GIT_SUCCESS))
- error = git__rethrow(error, "Failed to determine statuses. An error occured while post-processing the HEAD tree and the index");
+ error = git__rethrow(error,
+ "Failed to determine statuses. "
+ "An error occured while post-processing the HEAD tree and the index");
for (i = 0; i < entries.length; ++i) {
e = (struct status_entry *)git_vector_get(&entries, i);
@@ -451,7 +468,8 @@ int git_status_foreach(git_repository *repo, int (*callback)(const char *, unsig
if (error == GIT_SUCCESS) {
error = callback(e->path, e->status_flags, payload);
if (error < GIT_SUCCESS)
- error = git__rethrow(error, "Failed to determine statuses. User callback failed");
+ error = git__rethrow(error,
+ "Failed to determine statuses. User callback failed");
}
git__free(e);
@@ -460,7 +478,6 @@ int git_status_foreach(git_repository *repo, int (*callback)(const char *, unsig
exit:
git_vector_free(&entries);
git_tree_close(tree);
- git_index_free(index);
return error;
}
@@ -506,12 +523,19 @@ int git_status_file(unsigned int *status_flags, git_repository *repo, const char
char temp_path[GIT_PATH_MAX];
int error = GIT_SUCCESS;
git_tree *tree = NULL;
+ const char *workdir;
assert(status_flags && repo && path);
- git_path_join(temp_path, repo->path_workdir, path);
+ if ((workdir = git_repository_workdir(repo)) == NULL)
+ return git__throw(GIT_ERROR,
+ "Cannot retrieve status on a bare repository");
+
+ git_path_join(temp_path, workdir, path);
if (git_futils_isdir(temp_path) == GIT_SUCCESS)
- return git__throw(GIT_EINVALIDPATH, "Failed to determine status of file '%s'. Provided path leads to a folder, not a file", path);
+ return git__throw(GIT_EINVALIDPATH,
+ "Failed to determine status of file '%s'. "
+ "Given path leads to a folder, not a file", path);
e = status_entry_new(NULL, path);
if (e == NULL)
@@ -524,16 +548,18 @@ int git_status_file(unsigned int *status_flags, git_repository *repo, const char
}
/* Find file in Index */
- if ((error = git_repository_index(&index, repo)) < GIT_SUCCESS) {
- error = git__rethrow(error, "Failed to determine status of file '%s'. Index can't be opened", path);
+ if ((error = git_repository_index__weakptr(&index, repo)) < GIT_SUCCESS) {
+ error = git__rethrow(error,
+ "Failed to determine status of file '%s'."
+ "Index can't be opened", path);
goto exit;
}
status_entry_update_from_index(e, index);
- git_index_free(index);
if ((error = retrieve_head_tree(&tree, repo)) < GIT_SUCCESS) {
- error = git__rethrow(error, "Failed to determine status of file '%s'", path);
+ error = git__rethrow(error,
+ "Failed to determine status of file '%s'", path);
goto exit;
}
@@ -543,7 +569,9 @@ int git_status_file(unsigned int *status_flags, git_repository *repo, const char
error = recurse_tree_entry(tree, e, temp_path);
if (error < GIT_SUCCESS) {
- error = git__rethrow(error, "Failed to determine status of file '%s'. An error occured while processing the tree", path);
+ error = git__rethrow(error,
+ "Failed to determine status of file '%s'. "
+ "An error occured while processing the tree", path);
goto exit;
}
}
diff --git a/src/tag.c b/src/tag.c
index 7372e68c7..fd79dc326 100644
--- a/src/tag.c
+++ b/src/tag.c
@@ -175,6 +175,7 @@ static int write_tag_annotation(
{
int error = GIT_SUCCESS;
git_buf tag = GIT_BUF_INIT;
+ git_odb *odb;
git_oid__writebuf(&tag, "object ", git_object_id(target));
git_buf_printf(&tag, "type %s\n", git_object_type2string(git_object_type(target)));
@@ -188,7 +189,13 @@ static int write_tag_annotation(
return git__throw(GIT_ENOMEM, "Not enough memory to build the tag data");
}
- error = git_odb_write(oid, git_repository_database(repo), tag.ptr, tag.size, GIT_OBJ_TAG);
+ error = git_repository_odb__weakptr(&odb, repo);
+ if (error < GIT_SUCCESS) {
+ git_buf_free(&tag);
+ return error;
+ }
+
+ error = git_odb_write(oid, odb, tag.ptr, tag.size, GIT_OBJ_TAG);
git_buf_free(&tag);
if (error < GIT_SUCCESS)
@@ -286,6 +293,7 @@ int git_tag_create_frombuffer(git_oid *oid, git_repository *repo, const char *bu
{
git_tag tag;
int error, should_update_ref = 0;
+ git_odb *odb;
git_odb_stream *stream;
git_odb_object *target_obj;
@@ -296,12 +304,16 @@ int git_tag_create_frombuffer(git_oid *oid, git_repository *repo, const char *bu
memset(&tag, 0, sizeof(tag));
+ error = git_repository_odb__weakptr(&odb, repo);
+ if (error < GIT_SUCCESS)
+ return error;
+
/* validate the buffer */
if ((error = parse_tag_buffer(&tag, buffer, buffer + strlen(buffer))) < GIT_SUCCESS)
return git__rethrow(error, "Failed to create tag");
/* validate the target */
- if ((error = git_odb_read(&target_obj, repo->db, &tag.target)) < GIT_SUCCESS)
+ if ((error = git_odb_read(&target_obj, odb, &tag.target)) < GIT_SUCCESS)
return git__rethrow(error, "Failed to create tag");
if (tag.type != target_obj->raw.type)
@@ -334,7 +346,7 @@ int git_tag_create_frombuffer(git_oid *oid, git_repository *repo, const char *bu
}
/* write the buffer */
- if ((error = git_odb_open_wstream(&stream, repo->db, strlen(buffer), GIT_OBJ_TAG)) < GIT_SUCCESS) {
+ if ((error = git_odb_open_wstream(&stream, odb, strlen(buffer), GIT_OBJ_TAG)) < GIT_SUCCESS) {
git_reference_free(new_ref);
return git__rethrow(error, "Failed to create tag");
}
diff --git a/src/tree.c b/src/tree.c
index 92ca5ab77..ec44d2492 100644
--- a/src/tree.c
+++ b/src/tree.c
@@ -300,9 +300,15 @@ static int append_entry(git_treebuilder *bld, const char *filename, const git_oi
return GIT_SUCCESS;
}
-static int write_tree(git_oid *oid, git_index *index, const char *dirname, unsigned int start)
+static int write_tree(
+ git_oid *oid,
+ git_repository *repo,
+ git_index *index,
+ const char *dirname,
+ unsigned int start)
{
git_treebuilder *bld = NULL;
+
unsigned int i, entries = git_index_entrycount(index);
int error;
size_t dirname_len = strlen(dirname);
@@ -358,7 +364,7 @@ static int write_tree(git_oid *oid, git_index *index, const char *dirname, unsig
}
/* Write out the subtree */
- written = write_tree(&sub_oid, index, subdir, i);
+ written = write_tree(&sub_oid, repo, index, subdir, i);
if (written < 0) {
error = git__rethrow(written, "Failed to write subtree %s", subdir);
} else {
@@ -391,7 +397,7 @@ static int write_tree(git_oid *oid, git_index *index, const char *dirname, unsig
}
}
- error = git_treebuilder_write(oid, index->repository, bld);
+ error = git_treebuilder_write(oid, repo, bld);
if (error < GIT_SUCCESS)
error = git__rethrow(error, "Failed to write tree to db");
@@ -406,10 +412,15 @@ static int write_tree(git_oid *oid, git_index *index, const char *dirname, unsig
int git_tree_create_fromindex(git_oid *oid, git_index *index)
{
+ git_repository *repo;
int error;
- if (index->repository == NULL)
- return git__throw(GIT_EBAREINDEX, "Failed to create tree. The index file is not backed up by an existing repository");
+ repo = (git_repository *)GIT_REFCOUNT_OWNER(index);
+
+ if (repo == NULL)
+ return git__throw(GIT_EBAREINDEX,
+ "Failed to create tree. "
+ "The index file is not backed up by an existing repository");
if (index->tree != NULL && index->tree->entries >= 0) {
git_oid_cpy(oid, &index->tree->oid);
@@ -417,7 +428,7 @@ int git_tree_create_fromindex(git_oid *oid, git_index *index)
}
/* The tree cache didn't help us */
- error = write_tree(oid, index, "", 0);
+ error = write_tree(oid, repo, index, "", 0);
return (error < GIT_SUCCESS) ? git__rethrow(error, "Failed to create tree") : GIT_SUCCESS;
}
@@ -546,6 +557,7 @@ int git_treebuilder_write(git_oid *oid, git_repository *repo, git_treebuilder *b
unsigned int i;
int error;
git_buf tree = GIT_BUF_INIT;
+ git_odb *odb;
assert(bld);
@@ -570,7 +582,13 @@ int git_treebuilder_write(git_oid *oid, git_repository *repo, git_treebuilder *b
return git__throw(GIT_ENOMEM, "Not enough memory to build the tree data");
}
- error = git_odb_write(oid, git_repository_database(repo), tree.ptr, tree.size, GIT_OBJ_TREE);
+ error = git_repository_odb__weakptr(&odb, repo);
+ if (error < GIT_SUCCESS) {
+ git_buf_free(&tree);
+ return error;
+ }
+
+ error = git_odb_write(oid, odb, tree.ptr, tree.size, GIT_OBJ_TREE);
git_buf_free(&tree);
return error == GIT_SUCCESS ? GIT_SUCCESS : git__rethrow(error, "Failed to write tree");
diff --git a/src/util.h b/src/util.h
index fbf9012a3..2b239a0bf 100644
--- a/src/util.h
+++ b/src/util.h
@@ -129,4 +129,28 @@ extern void **git__bsearch(const void *key, void **base, size_t nmemb,
extern int git__strcmp_cb(const void *a, const void *b);
+typedef struct {
+ short refcount;
+ void *owner;
+} git_refcount;
+
+typedef void (*git_refcount_freeptr)(void *r);
+
+#define GIT_REFCOUNT_INC(r) { \
+ ((git_refcount *)(r))->refcount++; \
+}
+
+#define GIT_REFCOUNT_DEC(_r, do_free) { \
+ git_refcount *r = (git_refcount *)(_r); \
+ r->refcount--; \
+ if (r->refcount == 0 && r->owner == NULL) { do_free(_r); } \
+}
+
+#define GIT_REFCOUNT_OWN(r, o) { \
+ ((git_refcount *)(r))->owner = o; \
+}
+
+#define GIT_REFCOUNT_OWNER(r) (((git_refcount *)(r))->owner)
+
+
#endif /* INCLUDE_util_h__ */
diff --git a/tests-clay/clay.h b/tests-clay/clay.h
index 3db9600b3..b05a8247e 100644
--- a/tests-clay/clay.h
+++ b/tests-clay/clay.h
@@ -59,10 +59,30 @@ void cl_fixture_cleanup(const char *fixture_name);
*/
extern void test_buf_basic__printf(void);
extern void test_buf_basic__resize(void);
+extern void test_config_add__cleanup(void);
+extern void test_config_add__initialize(void);
+extern void test_config_add__to_existing_section(void);
+extern void test_config_add__to_new_section(void);
extern void test_config_new__write_new_config(void);
+extern void test_config_read__blank_lines(void);
+extern void test_config_read__case_sensitive(void);
+extern void test_config_read__empty_files(void);
+extern void test_config_read__header_in_last_line(void);
+extern void test_config_read__invalid_ext_headers(void);
+extern void test_config_read__lone_variable(void);
+extern void test_config_read__multiline_value(void);
+extern void test_config_read__number_suffixes(void);
+extern void test_config_read__prefixes(void);
+extern void test_config_read__simple_read(void);
+extern void test_config_read__subsection_header(void);
extern void test_config_stress__cleanup(void);
extern void test_config_stress__dont_break_on_invalid_input(void);
extern void test_config_stress__initialize(void);
+extern void test_config_write__cleanup(void);
+extern void test_config_write__delete_inexistent(void);
+extern void test_config_write__delete_value(void);
+extern void test_config_write__initialize(void);
+extern void test_config_write__replace_value(void);
extern void test_core_dirent__dont_traverse_dot(void);
extern void test_core_dirent__dont_traverse_empty_folders(void);
extern void test_core_dirent__traverse_slash_terminated_folder(void);
@@ -133,6 +153,31 @@ extern void test_object_tree_frompath__fail_when_processing_an_invalid_path(void
extern void test_object_tree_frompath__fail_when_processing_an_unknown_tree_segment(void);
extern void test_object_tree_frompath__initialize(void);
extern void test_object_tree_frompath__retrieve_tree_from_path_to_treeentry(void);
+extern void test_odb_loose__cleanup(void);
+extern void test_odb_loose__exists(void);
+extern void test_odb_loose__initialize(void);
+extern void test_odb_loose__simple_reads(void);
+extern void test_odb_packed__cleanup(void);
+extern void test_odb_packed__initialize(void);
+extern void test_odb_packed__mass_read(void);
+extern void test_odb_packed__read_header_0(void);
+extern void test_odb_packed__read_header_1(void);
+extern void test_odb_sorting__alternate_backends_sorting(void);
+extern void test_odb_sorting__basic_backends_sorting(void);
+extern void test_odb_sorting__cleanup(void);
+extern void test_odb_sorting__initialize(void);
+extern void test_repo_getters__cleanup(void);
+extern void test_repo_getters__empty(void);
+extern void test_repo_getters__head_detached(void);
+extern void test_repo_getters__head_orphan(void);
+extern void test_repo_getters__initialize(void);
+extern void test_repo_init__bare_repo(void);
+extern void test_repo_init__bare_repo_noslash(void);
+extern void test_repo_init__initialize(void);
+extern void test_repo_init__standard_repo(void);
+extern void test_repo_init__standard_repo_noslash(void);
+extern void test_repo_open__bare_empty_repo(void);
+extern void test_repo_open__standard_empty_repo(void);
extern void test_status_single__hash_single_file(void);
extern void test_status_worktree__cleanup(void);
extern void test_status_worktree__empty_repository(void);
diff --git a/tests-clay/clay_main.c b/tests-clay/clay_main.c
index 2f9a49d36..5c97057ec 100644
--- a/tests-clay/clay_main.c
+++ b/tests-clay/clay_main.c
@@ -108,12 +108,34 @@ static const struct clay_func _clay_cb_buf_basic[] = {
{"printf", &test_buf_basic__printf},
{"resize", &test_buf_basic__resize}
};
+static const struct clay_func _clay_cb_config_add[] = {
+ {"to_existing_section", &test_config_add__to_existing_section},
+ {"to_new_section", &test_config_add__to_new_section}
+};
static const struct clay_func _clay_cb_config_new[] = {
{"write_new_config", &test_config_new__write_new_config}
};
+static const struct clay_func _clay_cb_config_read[] = {
+ {"blank_lines", &test_config_read__blank_lines},
+ {"case_sensitive", &test_config_read__case_sensitive},
+ {"empty_files", &test_config_read__empty_files},
+ {"header_in_last_line", &test_config_read__header_in_last_line},
+ {"invalid_ext_headers", &test_config_read__invalid_ext_headers},
+ {"lone_variable", &test_config_read__lone_variable},
+ {"multiline_value", &test_config_read__multiline_value},
+ {"number_suffixes", &test_config_read__number_suffixes},
+ {"prefixes", &test_config_read__prefixes},
+ {"simple_read", &test_config_read__simple_read},
+ {"subsection_header", &test_config_read__subsection_header}
+};
static const struct clay_func _clay_cb_config_stress[] = {
{"dont_break_on_invalid_input", &test_config_stress__dont_break_on_invalid_input}
};
+static const struct clay_func _clay_cb_config_write[] = {
+ {"delete_inexistent", &test_config_write__delete_inexistent},
+ {"delete_value", &test_config_write__delete_value},
+ {"replace_value", &test_config_write__replace_value}
+};
static const struct clay_func _clay_cb_core_dirent[] = {
{"dont_traverse_dot", &test_core_dirent__dont_traverse_dot},
{"dont_traverse_empty_folders", &test_core_dirent__dont_traverse_empty_folders},
@@ -216,6 +238,34 @@ static const struct clay_func _clay_cb_object_tree_frompath[] = {
{"fail_when_processing_an_unknown_tree_segment", &test_object_tree_frompath__fail_when_processing_an_unknown_tree_segment},
{"retrieve_tree_from_path_to_treeentry", &test_object_tree_frompath__retrieve_tree_from_path_to_treeentry}
};
+static const struct clay_func _clay_cb_odb_loose[] = {
+ {"exists", &test_odb_loose__exists},
+ {"simple_reads", &test_odb_loose__simple_reads}
+};
+static const struct clay_func _clay_cb_odb_packed[] = {
+ {"mass_read", &test_odb_packed__mass_read},
+ {"read_header_0", &test_odb_packed__read_header_0},
+ {"read_header_1", &test_odb_packed__read_header_1}
+};
+static const struct clay_func _clay_cb_odb_sorting[] = {
+ {"alternate_backends_sorting", &test_odb_sorting__alternate_backends_sorting},
+ {"basic_backends_sorting", &test_odb_sorting__basic_backends_sorting}
+};
+static const struct clay_func _clay_cb_repo_getters[] = {
+ {"empty", &test_repo_getters__empty},
+ {"head_detached", &test_repo_getters__head_detached},
+ {"head_orphan", &test_repo_getters__head_orphan}
+};
+static const struct clay_func _clay_cb_repo_init[] = {
+ {"bare_repo", &test_repo_init__bare_repo},
+ {"bare_repo_noslash", &test_repo_init__bare_repo_noslash},
+ {"standard_repo", &test_repo_init__standard_repo},
+ {"standard_repo_noslash", &test_repo_init__standard_repo_noslash}
+};
+static const struct clay_func _clay_cb_repo_open[] = {
+ {"bare_empty_repo", &test_repo_open__bare_empty_repo},
+ {"standard_empty_repo", &test_repo_open__standard_empty_repo}
+};
static const struct clay_func _clay_cb_status_single[] = {
{"hash_single_file", &test_status_single__hash_single_file}
};
@@ -232,18 +282,36 @@ static const struct clay_suite _clay_suites[] = {
_clay_cb_buf_basic, 2
},
{
+ "config::add",
+ {"initialize", &test_config_add__initialize},
+ {"cleanup", &test_config_add__cleanup},
+ _clay_cb_config_add, 2
+ },
+ {
"config::new",
{NULL, NULL},
{NULL, NULL},
_clay_cb_config_new, 1
},
{
+ "config::read",
+ {NULL, NULL},
+ {NULL, NULL},
+ _clay_cb_config_read, 11
+ },
+ {
"config::stress",
{"initialize", &test_config_stress__initialize},
{"cleanup", &test_config_stress__cleanup},
_clay_cb_config_stress, 1
},
{
+ "config::write",
+ {"initialize", &test_config_write__initialize},
+ {"cleanup", &test_config_write__cleanup},
+ _clay_cb_config_write, 3
+ },
+ {
"core::dirent",
{NULL, NULL},
{NULL, NULL},
@@ -358,6 +426,42 @@ static const struct clay_suite _clay_suites[] = {
_clay_cb_object_tree_frompath, 3
},
{
+ "odb::loose",
+ {"initialize", &test_odb_loose__initialize},
+ {"cleanup", &test_odb_loose__cleanup},
+ _clay_cb_odb_loose, 2
+ },
+ {
+ "odb::packed",
+ {"initialize", &test_odb_packed__initialize},
+ {"cleanup", &test_odb_packed__cleanup},
+ _clay_cb_odb_packed, 3
+ },
+ {
+ "odb::sorting",
+ {"initialize", &test_odb_sorting__initialize},
+ {"cleanup", &test_odb_sorting__cleanup},
+ _clay_cb_odb_sorting, 2
+ },
+ {
+ "repo::getters",
+ {"initialize", &test_repo_getters__initialize},
+ {"cleanup", &test_repo_getters__cleanup},
+ _clay_cb_repo_getters, 3
+ },
+ {
+ "repo::init",
+ {"initialize", &test_repo_init__initialize},
+ {NULL, NULL},
+ _clay_cb_repo_init, 4
+ },
+ {
+ "repo::open",
+ {NULL, NULL},
+ {NULL, NULL},
+ _clay_cb_repo_open, 2
+ },
+ {
"status::single",
{NULL, NULL},
{NULL, NULL},
@@ -371,8 +475,8 @@ static const struct clay_suite _clay_suites[] = {
}
};
-static size_t _clay_suite_count = 24;
-static size_t _clay_callback_count = 71;
+static size_t _clay_suite_count = 33;
+static size_t _clay_callback_count = 103;
/* Core test functions */
static void
diff --git a/tests-clay/config/add.c b/tests-clay/config/add.c
new file mode 100644
index 000000000..de549af15
--- /dev/null
+++ b/tests-clay/config/add.c
@@ -0,0 +1,37 @@
+#include "clay_libgit2.h"
+
+void test_config_add__initialize(void)
+{
+ cl_fixture_sandbox("config/config10");
+}
+
+void test_config_add__cleanup(void)
+{
+ cl_fixture_cleanup("config10");
+}
+
+void test_config_add__to_existing_section(void)
+{
+ git_config *cfg;
+ int32_t i;
+
+ cl_git_pass(git_config_open_ondisk(&cfg, "config10"));
+ cl_git_pass(git_config_set_int32(cfg, "empty.tmp", 5));
+ cl_git_pass(git_config_get_int32(cfg, "empty.tmp", &i));
+ cl_assert(i == 5);
+ cl_git_pass(git_config_delete(cfg, "empty.tmp"));
+ git_config_free(cfg);
+}
+
+void test_config_add__to_new_section(void)
+{
+ git_config *cfg;
+ int32_t i;
+
+ cl_git_pass(git_config_open_ondisk(&cfg, "config10"));
+ cl_git_pass(git_config_set_int32(cfg, "section.tmp", 5));
+ cl_git_pass(git_config_get_int32(cfg, "section.tmp", &i));
+ cl_assert(i == 5);
+ cl_git_pass(git_config_delete(cfg, "section.tmp"));
+ git_config_free(cfg);
+}
diff --git a/tests-clay/config/read.c b/tests-clay/config/read.c
new file mode 100644
index 000000000..08dc03a88
--- /dev/null
+++ b/tests-clay/config/read.c
@@ -0,0 +1,209 @@
+#include "clay_libgit2.h"
+
+void test_config_read__simple_read(void)
+{
+ git_config *cfg;
+ int32_t i;
+
+ cl_git_pass(git_config_open_ondisk(&cfg, cl_fixture("config/config0")));
+
+ cl_git_pass(git_config_get_int32(cfg, "core.repositoryformatversion", &i));
+ cl_assert(i == 0);
+ cl_git_pass(git_config_get_bool(cfg, "core.filemode", &i));
+ cl_assert(i == 1);
+ cl_git_pass(git_config_get_bool(cfg, "core.bare", &i));
+ cl_assert(i == 0);
+ cl_git_pass(git_config_get_bool(cfg, "core.logallrefupdates", &i));
+ cl_assert(i == 1);
+
+ git_config_free(cfg);
+}
+
+void test_config_read__case_sensitive(void)
+{
+ git_config *cfg;
+ int i;
+ const char *str;
+
+ cl_git_pass(git_config_open_ondisk(&cfg, cl_fixture("config/config1")));
+
+ cl_git_pass(git_config_get_string(cfg, "this.that.other", &str));
+ cl_assert(!strcmp(str, "true"));
+ cl_git_pass(git_config_get_string(cfg, "this.That.other", &str));
+ cl_assert(!strcmp(str, "yes"));
+
+ cl_git_pass(git_config_get_bool(cfg, "this.that.other", &i));
+ cl_assert(i == 1);
+ cl_git_pass(git_config_get_bool(cfg, "this.That.other", &i));
+ cl_assert(i == 1);
+
+ /* This one doesn't exist */
+ cl_must_fail(git_config_get_bool(cfg, "this.thaT.other", &i));
+
+ git_config_free(cfg);
+}
+
+/*
+ * If \ is the last non-space character on the line, we read the next
+ * one, separating each line with SP.
+ */
+void test_config_read__multiline_value(void)
+{
+ git_config *cfg;
+ const char *str;
+
+ cl_git_pass(git_config_open_ondisk(&cfg, cl_fixture("config/config2")));
+
+ cl_git_pass(git_config_get_string(cfg, "this.That.and", &str));
+ cl_assert(!strcmp(str, "one one one two two three three"));
+
+ git_config_free(cfg);
+}
+
+/*
+ * This kind of subsection declaration is case-insensitive
+ */
+void test_config_read__subsection_header(void)
+{
+ git_config *cfg;
+ const char *str;
+
+ cl_git_pass(git_config_open_ondisk(&cfg, cl_fixture("config/config3")));
+
+ cl_git_pass(git_config_get_string(cfg, "section.subsection.var", &str));
+ cl_assert(!strcmp(str, "hello"));
+
+ /* The subsection is transformed to lower-case */
+ cl_must_fail(git_config_get_string(cfg, "section.subSectIon.var", &str));
+
+ git_config_free(cfg);
+}
+
+void test_config_read__lone_variable(void)
+{
+ git_config *cfg;
+ const char *str;
+ int i;
+
+ cl_git_pass(git_config_open_ondisk(&cfg, cl_fixture("config/config4")));
+
+ cl_git_pass(git_config_get_string(cfg, "some.section.variable", &str));
+ cl_assert(str == NULL);
+
+ cl_git_pass(git_config_get_bool(cfg, "some.section.variable", &i));
+ cl_assert(i == 1);
+
+ git_config_free(cfg);
+}
+
+void test_config_read__number_suffixes(void)
+{
+ git_config *cfg;
+ int64_t i;
+
+ cl_git_pass(git_config_open_ondisk(&cfg, cl_fixture("config/config5")));
+
+ cl_git_pass(git_config_get_int64(cfg, "number.simple", &i));
+ cl_assert(i == 1);
+
+ cl_git_pass(git_config_get_int64(cfg, "number.k", &i));
+ cl_assert(i == 1 * 1024);
+
+ cl_git_pass(git_config_get_int64(cfg, "number.kk", &i));
+ cl_assert(i == 1 * 1024);
+
+ cl_git_pass(git_config_get_int64(cfg, "number.m", &i));
+ cl_assert(i == 1 * 1024 * 1024);
+
+ cl_git_pass(git_config_get_int64(cfg, "number.mm", &i));
+ cl_assert(i == 1 * 1024 * 1024);
+
+ cl_git_pass(git_config_get_int64(cfg, "number.g", &i));
+ cl_assert(i == 1 * 1024 * 1024 * 1024);
+
+ cl_git_pass(git_config_get_int64(cfg, "number.gg", &i));
+ cl_assert(i == 1 * 1024 * 1024 * 1024);
+
+ git_config_free(cfg);
+}
+
+void test_config_read__blank_lines(void)
+{
+ git_config *cfg;
+ int i;
+
+ cl_git_pass(git_config_open_ondisk(&cfg, cl_fixture("config/config6")));
+
+ cl_git_pass(git_config_get_bool(cfg, "valid.subsection.something", &i));
+ cl_assert(i == 1);
+
+ cl_git_pass(git_config_get_bool(cfg, "something.else.something", &i));
+ cl_assert(i == 0);
+
+ git_config_free(cfg);
+}
+
+void test_config_read__invalid_ext_headers(void)
+{
+ git_config *cfg;
+ cl_must_fail(git_config_open_ondisk(&cfg, cl_fixture("config/config7")));
+}
+
+void test_config_read__empty_files(void)
+{
+ git_config *cfg;
+ cl_git_pass(git_config_open_ondisk(&cfg, cl_fixture("config/config8")));
+ git_config_free(cfg);
+}
+
+void test_config_read__header_in_last_line(void)
+{
+ git_config *cfg;
+
+ cl_git_pass(git_config_open_ondisk(&cfg, cl_fixture("config/config10")));
+ git_config_free(cfg);
+}
+
+void test_config_read__prefixes(void)
+{
+ git_config *cfg;
+ const char *str;
+
+ cl_git_pass(git_config_open_ondisk(&cfg, cl_fixture("config/config9")));
+ cl_git_pass(git_config_get_string(cfg, "remote.ab.url", &str));
+ cl_assert(strcmp(str, "http://example.com/git/ab") == 0);
+
+ cl_git_pass(git_config_get_string(cfg, "remote.abba.url", &str));
+ cl_assert(strcmp(str, "http://example.com/git/abba") == 0);
+
+ git_config_free(cfg);
+}
+
+#if 0
+
+BEGIN_TEST(config10, "a repo's config overrides the global config")
+ git_repository *repo;
+ git_config *cfg;
+ int32_t version;
+
+ cl_git_pass(git_repository_open(&repo, REPOSITORY_FOLDER));
+ cl_git_pass(git_repository_config(&cfg, repo, GLOBAL_CONFIG, NULL));
+ cl_git_pass(git_config_get_int32(cfg, "core.repositoryformatversion", &version));
+ cl_assert(version == 0);
+ git_config_free(cfg);
+ git_repository_free(repo);
+END_TEST
+
+BEGIN_TEST(config11, "fall back to the global config")
+ git_repository *repo;
+ git_config *cfg;
+ int32_t num;
+
+ cl_git_pass(git_repository_open(&repo, REPOSITORY_FOLDER));
+ cl_git_pass(git_repository_config(&cfg, repo, GLOBAL_CONFIG, NULL));
+ cl_git_pass(git_config_get_int32(cfg, "core.something", &num));
+ cl_assert(num == 2);
+ git_config_free(cfg);
+ git_repository_free(repo);
+END_TEST
+#endif
diff --git a/tests-clay/config/stress.c b/tests-clay/config/stress.c
index 832321556..b48ed399d 100644
--- a/tests-clay/config/stress.c
+++ b/tests-clay/config/stress.c
@@ -4,23 +4,21 @@
#include "fileops.h"
#include "posix.h"
-#define TEST_CONFIG "git-test-config"
-
void test_config_stress__initialize(void)
{
git_filebuf file = GIT_FILEBUF_INIT;
- git_filebuf_open(&file, TEST_CONFIG, 0);
+ cl_git_pass(git_filebuf_open(&file, "git-test-config", 0));
git_filebuf_printf(&file, "[color]\n\tui = auto\n");
git_filebuf_printf(&file, "[core]\n\teditor = \n");
- git_filebuf_commit(&file, 0666);
+ cl_git_pass(git_filebuf_commit(&file, 0666));
}
void test_config_stress__cleanup(void)
{
- p_unlink(TEST_CONFIG);
+ p_unlink("git-test-config");
}
void test_config_stress__dont_break_on_invalid_input(void)
@@ -29,8 +27,8 @@ void test_config_stress__dont_break_on_invalid_input(void)
struct git_config_file *file;
git_config *config;
- cl_git_pass(git_futils_exists(TEST_CONFIG));
- cl_git_pass(git_config_file__ondisk(&file, TEST_CONFIG));
+ cl_git_pass(git_futils_exists("git-test-config"));
+ cl_git_pass(git_config_file__ondisk(&file, "git-test-config"));
cl_git_pass(git_config_new(&config));
cl_git_pass(git_config_add_file(config, file, 0));
diff --git a/tests-clay/config/write.c b/tests-clay/config/write.c
new file mode 100644
index 000000000..57610ab63
--- /dev/null
+++ b/tests-clay/config/write.c
@@ -0,0 +1,77 @@
+#include "clay_libgit2.h"
+
+void test_config_write__initialize(void)
+{
+ cl_fixture_sandbox("config/config9");
+}
+
+void test_config_write__cleanup(void)
+{
+ cl_fixture_cleanup("config9");
+}
+
+void test_config_write__replace_value(void)
+{
+ git_config *cfg;
+ int i;
+ int64_t l, expected = +9223372036854775803;
+
+ /* By freeing the config, we make sure we flush the values */
+ cl_git_pass(git_config_open_ondisk(&cfg, "config9"));
+ cl_git_pass(git_config_set_int32(cfg, "core.dummy", 5));
+ git_config_free(cfg);
+
+ cl_git_pass(git_config_open_ondisk(&cfg, "config9"));
+ cl_git_pass(git_config_get_int32(cfg, "core.dummy", &i));
+ cl_assert(i == 5);
+ git_config_free(cfg);
+
+ cl_git_pass(git_config_open_ondisk(&cfg, "config9"));
+ cl_git_pass(git_config_set_int32(cfg, "core.dummy", 1));
+ git_config_free(cfg);
+
+ cl_git_pass(git_config_open_ondisk(&cfg, "config9"));
+ cl_git_pass(git_config_set_int64(cfg, "core.verylong", expected));
+ git_config_free(cfg);
+
+ cl_git_pass(git_config_open_ondisk(&cfg, "config9"));
+ cl_git_pass(git_config_get_int64(cfg, "core.verylong", &l));
+ cl_assert(l == expected);
+ git_config_free(cfg);
+
+ cl_git_pass(git_config_open_ondisk(&cfg, "config9"));
+ cl_must_fail(git_config_get_int32(cfg, "core.verylong", &i));
+ git_config_free(cfg);
+
+ cl_git_pass(git_config_open_ondisk(&cfg, "config9"));
+ cl_git_pass(git_config_set_int64(cfg, "core.verylong", 1));
+ git_config_free(cfg);
+}
+
+void test_config_write__delete_value(void)
+{
+ git_config *cfg;
+ int32_t i;
+
+ cl_git_pass(git_config_open_ondisk(&cfg, "config9"));
+ cl_git_pass(git_config_set_int32(cfg, "core.dummy", 5));
+ git_config_free(cfg);
+
+ cl_git_pass(git_config_open_ondisk(&cfg, "config9"));
+ cl_git_pass(git_config_delete(cfg, "core.dummy"));
+ git_config_free(cfg);
+
+ cl_git_pass(git_config_open_ondisk(&cfg, "config9"));
+ cl_assert(git_config_get_int32(cfg, "core.dummy", &i) == GIT_ENOTFOUND);
+ cl_git_pass(git_config_set_int32(cfg, "core.dummy", 1));
+ git_config_free(cfg);
+}
+
+void test_config_write__delete_inexistent(void)
+{
+ git_config *cfg;
+
+ cl_git_pass(git_config_open_ondisk(&cfg, "config9"));
+ cl_assert(git_config_delete(cfg, "core.imaginary") == GIT_ENOTFOUND);
+ git_config_free(cfg);
+}
diff --git a/tests-clay/network/remotes.c b/tests-clay/network/remotes.c
index a7cc742db..2c3a32e7f 100644
--- a/tests-clay/network/remotes.c
+++ b/tests-clay/network/remotes.c
@@ -1,45 +1,43 @@
#include "clay_libgit2.h"
-#define REPOSITORY_FOLDER "testrepo.git"
-
-static git_remote *remote;
-static git_repository *repo;
-static git_config *cfg;
-static const git_refspec *refspec;
+static git_remote *_remote;
+static git_repository *_repo;
+static const git_refspec *_refspec;
void test_network_remotes__initialize(void)
{
- cl_fixture_sandbox(REPOSITORY_FOLDER);
- cl_git_pass(git_repository_open(&repo, REPOSITORY_FOLDER));
- cl_git_pass(git_repository_config(&cfg, repo, NULL, NULL));
- cl_git_pass(git_remote_get(&remote, cfg, "test"));
- refspec = git_remote_fetchspec(remote);
- cl_assert(refspec != NULL);
+ cl_fixture_sandbox("testrepo.git");
+
+ cl_git_pass(git_repository_open(&_repo, "testrepo.git"));
+ cl_git_pass(git_remote_load(&_remote, _repo, "test"));
+
+ _refspec = git_remote_fetchspec(_remote);
+ cl_assert(_refspec != NULL);
}
void test_network_remotes__cleanup(void)
{
- git_config_free(cfg);
- git_repository_free(repo);
- git_remote_free(remote);
+ git_remote_free(_remote);
+ git_repository_free(_repo);
+ cl_fixture_cleanup("testrepo.git");
}
void test_network_remotes__parsing(void)
{
- cl_assert(!strcmp(git_remote_name(remote), "test"));
- cl_assert(!strcmp(git_remote_url(remote), "git://github.com/libgit2/libgit2"));
+ cl_assert(!strcmp(git_remote_name(_remote), "test"));
+ cl_assert(!strcmp(git_remote_url(_remote), "git://github.com/libgit2/libgit2"));
}
void test_network_remotes__refspec_parsing(void)
{
- cl_assert(!strcmp(git_refspec_src(refspec), "refs/heads/*"));
- cl_assert(!strcmp(git_refspec_dst(refspec), "refs/remotes/test/*"));
+ cl_assert(!strcmp(git_refspec_src(_refspec), "refs/heads/*"));
+ cl_assert(!strcmp(git_refspec_dst(_refspec), "refs/remotes/test/*"));
}
void test_network_remotes__fnmatch(void)
{
- cl_git_pass(git_refspec_src_match(refspec, "refs/heads/master"));
- cl_git_pass(git_refspec_src_match(refspec, "refs/heads/multi/level/branch"));
+ cl_git_pass(git_refspec_src_match(_refspec, "refs/heads/master"));
+ cl_git_pass(git_refspec_src_match(_refspec, "refs/heads/multi/level/branch"));
}
void test_network_remotes__transform(void)
@@ -47,6 +45,6 @@ void test_network_remotes__transform(void)
char ref[1024];
memset(ref, 0x0, sizeof(ref));
- cl_git_pass(git_refspec_transform(ref, sizeof(ref), refspec, "refs/heads/master"));
+ cl_git_pass(git_refspec_transform(ref, sizeof(ref), _refspec, "refs/heads/master"));
cl_assert(!strcmp(ref, "refs/remotes/test/master"));
}
diff --git a/tests-clay/object/tree/frompath.c b/tests-clay/object/tree/frompath.c
index 1effcb1db..7d6f42d6f 100644
--- a/tests-clay/object/tree/frompath.c
+++ b/tests-clay/object/tree/frompath.c
@@ -1,7 +1,5 @@
#include "clay_libgit2.h"
-#define REPOSITORY_FOLDER "testrepo.git"
-
static git_repository *repo;
const char *tree_with_subtrees_oid = "ae90f12eea699729ed24555e40b9fd669da12a12";
static git_tree *tree;
@@ -10,8 +8,8 @@ void test_object_tree_frompath__initialize(void)
{
git_oid id;
- cl_fixture_sandbox(REPOSITORY_FOLDER);
- cl_git_pass(git_repository_open(&repo, REPOSITORY_FOLDER));
+ cl_fixture_sandbox("testrepo.git");
+ cl_git_pass(git_repository_open(&repo, "testrepo.git"));
cl_assert(repo != NULL);
cl_git_pass(git_oid_fromstr(&id, tree_with_subtrees_oid));
@@ -23,6 +21,7 @@ void test_object_tree_frompath__cleanup(void)
{
git_tree_close(tree);
git_repository_free(repo);
+ cl_fixture_cleanup("testrepo.git");
}
static void assert_tree_from_path(git_tree *root, const char *path, git_error expected_result, const char *expected_raw_oid)
diff --git a/tests-clay/odb/loose.c b/tests-clay/odb/loose.c
new file mode 100644
index 000000000..756a157df
--- /dev/null
+++ b/tests-clay/odb/loose.c
@@ -0,0 +1,84 @@
+#include "clay_libgit2.h"
+#include "odb.h"
+#include "posix.h"
+#include "loose_data.h"
+
+static void write_object_files(object_data *d)
+{
+ int fd;
+
+ if (p_mkdir(d->dir, GIT_OBJECT_DIR_MODE) < 0)
+ cl_assert(errno == EEXIST);
+
+ cl_assert((fd = p_creat(d->file, S_IREAD | S_IWRITE)) >= 0);
+ cl_must_pass(p_write(fd, d->bytes, d->blen));
+
+ p_close(fd);
+}
+
+static void cmp_objects(git_rawobj *o, object_data *d)
+{
+ cl_assert(o->type == git_object_string2type(d->type));
+ cl_assert(o->len == d->dlen);
+
+ if (o->len > 0)
+ cl_assert(memcmp(o->data, d->data, o->len) == 0);
+}
+
+static void test_read_object(object_data *data)
+{
+ git_oid id;
+ git_odb_object *obj;
+ git_odb *odb;
+
+ write_object_files(data);
+
+ cl_git_pass(git_odb_open(&odb, "test-objects"));
+ cl_git_pass(git_oid_fromstr(&id, data->id));
+ cl_git_pass(git_odb_read(&obj, odb, &id));
+
+ cmp_objects((git_rawobj *)&obj->raw, data);
+
+ git_odb_object_close(obj);
+ git_odb_free(odb);
+}
+
+void test_odb_loose__initialize(void)
+{
+ cl_must_pass(p_mkdir("test-objects", GIT_OBJECT_DIR_MODE));
+}
+
+void test_odb_loose__cleanup(void)
+{
+ cl_fixture_cleanup("test-objects");
+}
+
+void test_odb_loose__exists(void)
+{
+ git_oid id, id2;
+ git_odb *odb;
+
+ write_object_files(&one);
+ cl_git_pass(git_odb_open(&odb, "test-objects"));
+
+ cl_git_pass(git_oid_fromstr(&id, one.id));
+
+ cl_assert(git_odb_exists(odb, &id));
+
+ /* Test for a non-existant object */
+ cl_git_pass(git_oid_fromstr(&id2, "8b137891791fe96927ad78e64b0aad7bded08baa"));
+ cl_assert(!git_odb_exists(odb, &id2));
+
+ git_odb_free(odb);
+}
+
+void test_odb_loose__simple_reads(void)
+{
+ test_read_object(&commit);
+ test_read_object(&tree);
+ test_read_object(&tag);
+ test_read_object(&zero);
+ test_read_object(&one);
+ test_read_object(&two);
+ test_read_object(&some);
+}
diff --git a/tests/t02-data.h b/tests-clay/odb/loose_data.h
index 705a2d7af..c10c9bc7f 100644
--- a/tests/t02-data.h
+++ b/tests-clay/odb/loose_data.h
@@ -1,5 +1,13 @@
-
-static char *odb_dir = "test-objects";
+typedef struct object_data {
+ unsigned char *bytes; /* (compressed) bytes stored in object store */
+ size_t blen; /* length of data in object store */
+ char *id; /* object id (sha1) */
+ char *type; /* object type */
+ char *dir; /* object store (fan-out) directory name */
+ char *file; /* object store filename */
+ unsigned char *data; /* (uncompressed) object data */
+ size_t dlen; /* length of (uncompressed) object data */
+} object_data;
/* one == 8b137891791fe96927ad78e64b0aad7bded08bdc */
static unsigned char one_bytes[] = {
@@ -512,4 +520,3 @@ static object_data some = {
some_data,
sizeof(some_data),
};
-
diff --git a/tests/t02-oids.h b/tests-clay/odb/pack_data.h
index 1a5ed5df0..e6371beb1 100644
--- a/tests/t02-oids.h
+++ b/tests-clay/odb/pack_data.h
@@ -149,4 +149,3 @@ static const char *loose_objects[] = {
"a4a7dce85cf63874e984719f4fdd239f5145052f",
"4a202b346bb0fb0db7eff3cffeb3c70babbd2045"
};
-
diff --git a/tests-clay/odb/packed.c b/tests-clay/odb/packed.c
new file mode 100644
index 000000000..e50bca631
--- /dev/null
+++ b/tests-clay/odb/packed.c
@@ -0,0 +1,77 @@
+#include "clay_libgit2.h"
+#include "odb.h"
+#include "pack_data.h"
+
+static git_odb *_odb;
+
+void test_odb_packed__initialize(void)
+{
+ cl_git_pass(git_odb_open(&_odb, cl_fixture("testrepo.git/objects")));
+}
+
+void test_odb_packed__cleanup(void)
+{
+ git_odb_free(_odb);
+}
+
+void test_odb_packed__mass_read(void)
+{
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(packed_objects); ++i) {
+ git_oid id;
+ git_odb_object *obj;
+
+ cl_git_pass(git_oid_fromstr(&id, packed_objects[i]));
+ cl_assert(git_odb_exists(_odb, &id) == 1);
+ cl_git_pass(git_odb_read(&obj, _odb, &id));
+
+ git_odb_object_close(obj);
+ }
+}
+
+void test_odb_packed__read_header_0(void)
+{
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(packed_objects); ++i) {
+ git_oid id;
+ git_odb_object *obj;
+ size_t len;
+ git_otype type;
+
+ cl_git_pass(git_oid_fromstr(&id, packed_objects[i]));
+
+ cl_git_pass(git_odb_read(&obj, _odb, &id));
+ cl_git_pass(git_odb_read_header(&len, &type, _odb, &id));
+
+ cl_assert(obj->raw.len == len);
+ cl_assert(obj->raw.type == type);
+
+ git_odb_object_close(obj);
+ }
+}
+
+void test_odb_packed__read_header_1(void)
+{
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(loose_objects); ++i) {
+ git_oid id;
+ git_odb_object *obj;
+ size_t len;
+ git_otype type;
+
+ cl_git_pass(git_oid_fromstr(&id, loose_objects[i]));
+
+ cl_assert(git_odb_exists(_odb, &id) == 1);
+
+ cl_git_pass(git_odb_read(&obj, _odb, &id));
+ cl_git_pass(git_odb_read_header(&len, &type, _odb, &id));
+
+ cl_assert(obj->raw.len == len);
+ cl_assert(obj->raw.type == type);
+
+ git_odb_object_close(obj);
+ }
+}
diff --git a/tests-clay/odb/sorting.c b/tests-clay/odb/sorting.c
new file mode 100644
index 000000000..779660707
--- /dev/null
+++ b/tests-clay/odb/sorting.c
@@ -0,0 +1,71 @@
+#include "clay_libgit2.h"
+#include "git2/odb_backend.h"
+#include "odb.h"
+
+typedef struct {
+ git_odb_backend base;
+ int position;
+} fake_backend;
+
+static git_odb_backend *new_backend(int position)
+{
+ fake_backend *b;
+
+ b = git__malloc(sizeof(fake_backend));
+ if (b == NULL)
+ return NULL;
+
+ memset(b, 0x0, sizeof(fake_backend));
+ b->position = position;
+ return (git_odb_backend *)b;
+}
+
+static void check_backend_sorting(git_odb *odb)
+{
+ unsigned int i;
+
+ for (i = 0; i < odb->backends.length; ++i) {
+ fake_backend *internal =
+ *((fake_backend **)git_vector_get(&odb->backends, i));
+
+ cl_assert(internal != NULL);
+ cl_assert(internal->position == (int)i);
+ }
+}
+
+static git_odb *_odb;
+
+void test_odb_sorting__initialize(void)
+{
+ cl_git_pass(git_odb_new(&_odb));
+}
+
+void test_odb_sorting__cleanup(void)
+{
+ git_odb_free(_odb);
+ _odb = NULL;
+}
+
+void test_odb_sorting__basic_backends_sorting(void)
+{
+ cl_git_pass(git_odb_add_backend(_odb, new_backend(0), 5));
+ cl_git_pass(git_odb_add_backend(_odb, new_backend(2), 3));
+ cl_git_pass(git_odb_add_backend(_odb, new_backend(1), 4));
+ cl_git_pass(git_odb_add_backend(_odb, new_backend(3), 1));
+
+ check_backend_sorting(_odb);
+}
+
+void test_odb_sorting__alternate_backends_sorting(void)
+{
+ cl_git_pass(git_odb_add_backend(_odb, new_backend(0), 5));
+ cl_git_pass(git_odb_add_backend(_odb, new_backend(2), 3));
+ cl_git_pass(git_odb_add_backend(_odb, new_backend(1), 4));
+ cl_git_pass(git_odb_add_backend(_odb, new_backend(3), 1));
+ cl_git_pass(git_odb_add_alternate(_odb, new_backend(4), 5));
+ cl_git_pass(git_odb_add_alternate(_odb, new_backend(6), 3));
+ cl_git_pass(git_odb_add_alternate(_odb, new_backend(5), 4));
+ cl_git_pass(git_odb_add_alternate(_odb, new_backend(7), 1));
+
+ check_backend_sorting(_odb);
+}
diff --git a/tests-clay/repo/getters.c b/tests-clay/repo/getters.c
new file mode 100644
index 000000000..3acdb7566
--- /dev/null
+++ b/tests-clay/repo/getters.c
@@ -0,0 +1,68 @@
+#include "clay_libgit2.h"
+
+void test_repo_getters__initialize(void)
+{
+ cl_fixture_sandbox("testrepo.git");
+}
+
+void test_repo_getters__cleanup(void)
+{
+ cl_fixture_cleanup("testrepo.git");
+}
+
+void test_repo_getters__empty(void)
+{
+ git_repository *repo_empty, *repo_normal;
+
+ cl_git_pass(git_repository_open(&repo_normal, cl_fixture("testrepo.git")));
+ cl_assert(git_repository_is_empty(repo_normal) == 0);
+ git_repository_free(repo_normal);
+
+ cl_git_pass(git_repository_open(&repo_empty, cl_fixture("empty_bare.git")));
+ cl_assert(git_repository_is_empty(repo_empty) == 1);
+ git_repository_free(repo_empty);
+}
+
+void test_repo_getters__head_detached(void)
+{
+ git_repository *repo;
+ git_reference *ref;
+ git_oid oid;
+
+ cl_git_pass(git_repository_open(&repo, "testrepo.git"));
+
+ cl_assert(git_repository_head_detached(repo) == 0);
+
+ /* detach the HEAD */
+ git_oid_fromstr(&oid, "c47800c7266a2be04c571c04d5a6614691ea99bd");
+ cl_git_pass(git_reference_create_oid(&ref, repo, "HEAD", &oid, 1));
+ cl_assert(git_repository_head_detached(repo) == 1);
+
+ /* take the reop back to it's original state */
+ cl_git_pass(git_reference_create_symbolic(&ref, repo, "HEAD", "refs/heads/master", 1));
+ cl_assert(git_repository_head_detached(repo) == 0);
+
+ git_reference_free(ref);
+ git_repository_free(repo);
+}
+
+void test_repo_getters__head_orphan(void)
+{
+ git_repository *repo;
+ git_reference *ref;
+
+ cl_git_pass(git_repository_open(&repo, "testrepo.git"));
+
+ cl_assert(git_repository_head_orphan(repo) == 0);
+
+ /* orphan HEAD */
+ cl_git_pass(git_reference_create_symbolic(&ref, repo, "HEAD", "refs/heads/orphan", 1));
+ cl_assert(git_repository_head_orphan(repo) == 1);
+
+ /* take the reop back to it's original state */
+ cl_git_pass(git_reference_create_symbolic(&ref, repo, "HEAD", "refs/heads/master", 1));
+ cl_assert(git_repository_head_orphan(repo) == 0);
+
+ git_reference_free(ref);
+ git_repository_free(repo);
+}
diff --git a/tests-clay/repo/init.c b/tests-clay/repo/init.c
new file mode 100644
index 000000000..95cd704e9
--- /dev/null
+++ b/tests-clay/repo/init.c
@@ -0,0 +1,104 @@
+#include "clay_libgit2.h"
+#include "fileops.h"
+
+enum repo_mode {
+ STANDARD_REPOSITORY = 0,
+ BARE_REPOSITORY = 1
+};
+
+static git_repository *_repo;
+
+void test_repo_init__initialize(void)
+{
+ _repo = NULL;
+}
+
+static void cleanup_repository(void *path)
+{
+ git_repository_free(_repo);
+ cl_fixture_cleanup((const char *)path);
+}
+
+static void ensure_repository_init(
+ const char *working_directory,
+ int is_bare,
+ const char *expected_path_repository,
+ const char *expected_working_directory)
+{
+ const char *workdir;
+
+ cl_git_pass(git_repository_init(&_repo, working_directory, is_bare));
+
+ workdir = git_repository_workdir(_repo);
+ if (workdir != NULL || expected_working_directory != NULL) {
+ cl_assert(
+ git__suffixcmp(workdir, expected_working_directory) == 0
+ );
+ }
+
+ cl_assert(
+ git__suffixcmp(git_repository_path(_repo), expected_path_repository) == 0
+ );
+
+ cl_assert(git_repository_is_bare(_repo) == is_bare);
+
+#ifdef GIT_WIN32
+ if (!is_bare) {
+ cl_assert((GetFileAttributes(_repo->path_repository) & FILE_ATTRIBUTE_HIDDEN) != 0);
+ }
+#endif
+
+ cl_assert(git_repository_is_empty(_repo));
+}
+
+void test_repo_init__standard_repo(void)
+{
+ cl_set_cleanup(&cleanup_repository, "testrepo");
+ ensure_repository_init("testrepo/", 0, "testrepo/.git/", "testrepo/");
+}
+
+void test_repo_init__standard_repo_noslash(void)
+{
+ cl_set_cleanup(&cleanup_repository, "testrepo");
+ ensure_repository_init("testrepo", 0, "testrepo/.git/", "testrepo/");
+}
+
+void test_repo_init__bare_repo(void)
+{
+ cl_set_cleanup(&cleanup_repository, "testrepo.git");
+ ensure_repository_init("testrepo.git/", 1, "testrepo.git/", NULL);
+}
+
+void test_repo_init__bare_repo_noslash(void)
+{
+ cl_set_cleanup(&cleanup_repository, "testrepo.git");
+ ensure_repository_init("testrepo.git", 1, "testrepo.git/", NULL);
+}
+
+#if 0
+BEGIN_TEST(init2, "Initialize and open a bare repo with a relative path escaping out of the current working directory")
+ char path_repository[GIT_PATH_MAX];
+ char current_workdir[GIT_PATH_MAX];
+ const mode_t mode = 0777;
+ git_repository* repo;
+
+ must_pass(p_getcwd(current_workdir, sizeof(current_workdir)));
+
+ git_path_join(path_repository, TEMP_REPO_FOLDER, "a/b/c/");
+ must_pass(git_futils_mkdir_r(path_repository, mode));
+
+ must_pass(chdir(path_repository));
+
+ must_pass(git_repository_init(&repo, "../d/e.git", 1));
+ must_pass(git__suffixcmp(repo->path_repository, "/a/b/d/e.git/"));
+
+ git_repository_free(repo);
+
+ must_pass(git_repository_open(&repo, "../d/e.git"));
+
+ git_repository_free(repo);
+
+ must_pass(chdir(current_workdir));
+ must_pass(git_futils_rmdir_r(TEMP_REPO_FOLDER, 1));
+END_TEST
+#endif
diff --git a/tests-clay/repo/open.c b/tests-clay/repo/open.c
new file mode 100644
index 000000000..235af1447
--- /dev/null
+++ b/tests-clay/repo/open.c
@@ -0,0 +1,54 @@
+#include "clay_libgit2.h"
+#include "posix.h"
+
+void test_repo_open__bare_empty_repo(void)
+{
+ git_repository *repo;
+
+ cl_git_pass(git_repository_open(&repo, cl_fixture("empty_bare.git")));
+ cl_assert(git_repository_path(repo) != NULL);
+ cl_assert(git_repository_workdir(repo) == NULL);
+
+ git_repository_free(repo);
+}
+
+void test_repo_open__standard_empty_repo(void)
+{
+ git_repository *repo;
+
+ cl_git_pass(git_repository_open(&repo, cl_fixture("empty_standard_repo/.gitted")));
+ cl_assert(git_repository_path(repo) != NULL);
+ cl_assert(git_repository_workdir(repo) != NULL);
+
+ git_repository_free(repo);
+}
+
+/* TODO TODO */
+#if 0
+BEGIN_TEST(open2, "Open a bare repository with a relative path escaping out of the current working directory")
+ char new_current_workdir[GIT_PATH_MAX];
+ char current_workdir[GIT_PATH_MAX];
+ char path_repository[GIT_PATH_MAX];
+
+ const mode_t mode = 0777;
+ git_repository* repo;
+
+ /* Setup the repository to open */
+ must_pass(p_getcwd(current_workdir, sizeof(current_workdir)));
+ strcpy(path_repository, current_workdir);
+ git_path_join_n(path_repository, 3, path_repository, TEMP_REPO_FOLDER, "a/d/e.git");
+ must_pass(copydir_recurs(REPOSITORY_FOLDER, path_repository));
+
+ /* Change the current working directory */
+ git_path_join(new_current_workdir, TEMP_REPO_FOLDER, "a/b/c/");
+ must_pass(git_futils_mkdir_r(new_current_workdir, mode));
+ must_pass(chdir(new_current_workdir));
+
+ must_pass(git_repository_open(&repo, "../../d/e.git"));
+
+ git_repository_free(repo);
+
+ must_pass(chdir(current_workdir));
+ must_pass(git_futils_rmdir_r(TEMP_REPO_FOLDER, 1));
+END_TEST
+#endif
diff --git a/tests/t02-objread.c b/tests/t02-objread.c
deleted file mode 100644
index 4bcff2742..000000000
--- a/tests/t02-objread.c
+++ /dev/null
@@ -1,269 +0,0 @@
-/*
- * This file is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License, version 2,
- * as published by the Free Software Foundation.
- *
- * In addition to the permissions in the GNU General Public License,
- * the authors give you unlimited permission to link the compiled
- * version of this file into combinations with other programs,
- * and to distribute those combinations without any restriction
- * coming from the use of this file. (The General Public License
- * restrictions do apply in other respects; for example, they cover
- * modification of the file, and distribution when not linked into
- * a combined executable.)
- *
- * This file is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; see the file COPYING. If not, write to
- * the Free Software Foundation, 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-#include "test_lib.h"
-#include "test_helpers.h"
-#include "odb.h"
-
-#include "t02-data.h"
-#include "t02-oids.h"
-
-
-BEGIN_TEST(existsloose0, "check if a loose object exists on the odb")
- git_odb *db;
- git_oid id, id2;
-
- must_pass(write_object_files(odb_dir, &one));
- must_pass(git_odb_open(&db, odb_dir));
- must_pass(git_oid_fromstr(&id, one.id));
-
- must_be_true(git_odb_exists(db, &id));
-
- /* Test for a non-existant object */
- must_pass(git_oid_fromstr(&id2, "8b137891791fe96927ad78e64b0aad7bded08baa"));
- must_be_true(0 == git_odb_exists(db, &id2));
-
- git_odb_close(db);
- must_pass(remove_object_files(odb_dir, &one));
-END_TEST
-
-BEGIN_TEST(readloose0, "read a loose commit")
- git_odb *db;
- git_oid id;
- git_odb_object *obj;
-
- must_pass(write_object_files(odb_dir, &commit));
- must_pass(git_odb_open(&db, odb_dir));
- must_pass(git_oid_fromstr(&id, commit.id));
-
- must_pass(git_odb_read(&obj, db, &id));
- must_pass(cmp_objects((git_rawobj *)&obj->raw, &commit));
-
- git_odb_object_close(obj);
- git_odb_close(db);
- must_pass(remove_object_files(odb_dir, &commit));
-END_TEST
-
-BEGIN_TEST(readloose1, "read a loose tree")
- git_odb *db;
- git_oid id;
- git_odb_object *obj;
-
- must_pass(write_object_files(odb_dir, &tree));
- must_pass(git_odb_open(&db, odb_dir));
- must_pass(git_oid_fromstr(&id, tree.id));
-
- must_pass(git_odb_read(&obj, db, &id));
- must_pass(cmp_objects((git_rawobj *)&obj->raw, &tree));
-
- git_odb_object_close(obj);
- git_odb_close(db);
- must_pass(remove_object_files(odb_dir, &tree));
-END_TEST
-
-BEGIN_TEST(readloose2, "read a loose tag")
- git_odb *db;
- git_oid id;
- git_odb_object *obj;
-
- must_pass(write_object_files(odb_dir, &tag));
- must_pass(git_odb_open(&db, odb_dir));
- must_pass(git_oid_fromstr(&id, tag.id));
-
- must_pass(git_odb_read(&obj, db, &id));
- must_pass(cmp_objects((git_rawobj *)&obj->raw, &tag));
-
- git_odb_object_close(obj);
- git_odb_close(db);
- must_pass(remove_object_files(odb_dir, &tag));
-END_TEST
-
-BEGIN_TEST(readloose3, "read a loose zero-bytes object")
- git_odb *db;
- git_oid id;
- git_odb_object *obj;
-
- must_pass(write_object_files(odb_dir, &zero));
- must_pass(git_odb_open(&db, odb_dir));
- must_pass(git_oid_fromstr(&id, zero.id));
-
- must_pass(git_odb_read(&obj, db, &id));
- must_pass(cmp_objects((git_rawobj *)&obj->raw, &zero));
-
- git_odb_object_close(obj);
- git_odb_close(db);
- must_pass(remove_object_files(odb_dir, &zero));
-END_TEST
-
-BEGIN_TEST(readloose4, "read a one-byte long loose object")
- git_odb *db;
- git_oid id;
- git_odb_object *obj;
-
- must_pass(write_object_files(odb_dir, &one));
- must_pass(git_odb_open(&db, odb_dir));
- must_pass(git_oid_fromstr(&id, one.id));
-
- must_pass(git_odb_read(&obj, db, &id));
- must_pass(cmp_objects(&obj->raw, &one));
-
- git_odb_object_close(obj);
- git_odb_close(db);
- must_pass(remove_object_files(odb_dir, &one));
-END_TEST
-
-BEGIN_TEST(readloose5, "read a two-bytes long loose object")
- git_odb *db;
- git_oid id;
- git_odb_object *obj;
-
- must_pass(write_object_files(odb_dir, &two));
- must_pass(git_odb_open(&db, odb_dir));
- must_pass(git_oid_fromstr(&id, two.id));
-
- must_pass(git_odb_read(&obj, db, &id));
- must_pass(cmp_objects(&obj->raw, &two));
-
- git_odb_object_close(obj);
- git_odb_close(db);
- must_pass(remove_object_files(odb_dir, &two));
-END_TEST
-
-BEGIN_TEST(readloose6, "read a loose object which is several bytes long")
- git_odb *db;
- git_oid id;
- git_odb_object *obj;
-
- must_pass(write_object_files(odb_dir, &some));
- must_pass(git_odb_open(&db, odb_dir));
- must_pass(git_oid_fromstr(&id, some.id));
-
- must_pass(git_odb_read(&obj, db, &id));
- must_pass(cmp_objects(&obj->raw, &some));
-
- git_odb_object_close(obj);
- git_odb_close(db);
- must_pass(remove_object_files(odb_dir, &some));
-END_TEST
-
-BEGIN_TEST(readpack0, "read several packed objects")
- unsigned int i;
- git_odb *db;
-
- must_pass(git_odb_open(&db, ODB_FOLDER));
-
- for (i = 0; i < ARRAY_SIZE(packed_objects); ++i) {
- git_oid id;
- git_odb_object *obj;
-
- must_pass(git_oid_fromstr(&id, packed_objects[i]));
- must_be_true(git_odb_exists(db, &id) == 1);
- must_pass(git_odb_read(&obj, db, &id));
-
- git_odb_object_close(obj);
- }
-
- git_odb_close(db);
-END_TEST
-
-BEGIN_TEST(readheader0, "read only the header of several packed objects")
- unsigned int i;
- git_odb *db;
-
- must_pass(git_odb_open(&db, ODB_FOLDER));
-
- for (i = 0; i < ARRAY_SIZE(packed_objects); ++i) {
- git_oid id;
- git_odb_object *obj;
- size_t len;
- git_otype type;
-
- must_pass(git_oid_fromstr(&id, packed_objects[i]));
-
- must_pass(git_odb_read(&obj, db, &id));
- must_pass(git_odb_read_header(&len, &type, db, &id));
-
- must_be_true(obj->raw.len == len);
- must_be_true(obj->raw.type == type);
-
- git_odb_object_close(obj);
- }
-
- git_odb_close(db);
-END_TEST
-
-BEGIN_TEST(readheader1, "read only the header of several loose objects")
- unsigned int i;
- git_odb *db;
-
- must_pass(git_odb_open(&db, ODB_FOLDER));
-
- for (i = 0; i < ARRAY_SIZE(loose_objects); ++i) {
- git_oid id;
- git_odb_object *obj;
- size_t len;
- git_otype type;
-
- must_pass(git_oid_fromstr(&id, loose_objects[i]));
-
- must_be_true(git_odb_exists(db, &id) == 1);
-
- must_pass(git_odb_read(&obj, db, &id));
- must_pass(git_odb_read_header(&len, &type, db, &id));
-
- must_be_true(obj->raw.len == len);
- must_be_true(obj->raw.type == type);
-
- git_odb_object_close(obj);
- }
-
- git_odb_close(db);
-END_TEST
-
-BEGIN_SUITE(objread)
- ADD_TEST(existsloose0);
-
- ADD_TEST(readloose0);
- ADD_TEST(readloose1);
- ADD_TEST(readloose2);
- ADD_TEST(readloose3);
- ADD_TEST(readloose4);
- ADD_TEST(readloose5);
- ADD_TEST(readloose6);
-
-/*
- ADD_TEST(readloose_enc0);
- ADD_TEST(readloose_enc1);
- ADD_TEST(readloose_enc2);
- ADD_TEST(readloose_enc3);
- ADD_TEST(readloose_enc4);
- ADD_TEST(readloose_enc5);
- ADD_TEST(readloose_enc6);
-*/
-
- ADD_TEST(readpack0);
-
- ADD_TEST(readheader0);
- ADD_TEST(readheader1);
-END_SUITE
diff --git a/tests/t03-objwrite.c b/tests/t03-objwrite.c
index 7563d0e3a..6cf3834c2 100644
--- a/tests/t03-objwrite.c
+++ b/tests/t03-objwrite.c
@@ -114,7 +114,7 @@ BEGIN_TEST(write0, "write loose commit object")
must_pass(cmp_objects(&obj->raw, &commit_obj));
git_odb_object_close(obj);
- git_odb_close(db);
+ git_odb_free(db);
must_pass(remove_object_files(&commit));
END_TEST
@@ -135,7 +135,7 @@ BEGIN_TEST(write1, "write loose tree object")
must_pass(cmp_objects(&obj->raw, &tree_obj));
git_odb_object_close(obj);
- git_odb_close(db);
+ git_odb_free(db);
must_pass(remove_object_files(&tree));
END_TEST
@@ -156,7 +156,7 @@ BEGIN_TEST(write2, "write loose tag object")
must_pass(cmp_objects(&obj->raw, &tag_obj));
git_odb_object_close(obj);
- git_odb_close(db);
+ git_odb_free(db);
must_pass(remove_object_files(&tag));
END_TEST
@@ -177,7 +177,7 @@ BEGIN_TEST(write3, "write zero-length object")
must_pass(cmp_objects(&obj->raw, &zero_obj));
git_odb_object_close(obj);
- git_odb_close(db);
+ git_odb_free(db);
must_pass(remove_object_files(&zero));
END_TEST
@@ -198,7 +198,7 @@ BEGIN_TEST(write4, "write one-byte long object")
must_pass(cmp_objects(&obj->raw, &one_obj));
git_odb_object_close(obj);
- git_odb_close(db);
+ git_odb_free(db);
must_pass(remove_object_files(&one));
END_TEST
@@ -219,7 +219,7 @@ BEGIN_TEST(write5, "write two-byte long object")
must_pass(cmp_objects(&obj->raw, &two_obj));
git_odb_object_close(obj);
- git_odb_close(db);
+ git_odb_free(db);
must_pass(remove_object_files(&two));
END_TEST
@@ -240,7 +240,7 @@ BEGIN_TEST(write6, "write an object which is several bytes long")
must_pass(cmp_objects(&obj->raw, &some_obj));
git_odb_object_close(obj);
- git_odb_close(db);
+ git_odb_free(db);
must_pass(remove_object_files(&some));
END_TEST
diff --git a/tests/t12-repo.c b/tests/t12-repo.c
index 47dc852f3..acf8b743d 100644
--- a/tests/t12-repo.c
+++ b/tests/t12-repo.c
@@ -29,288 +29,8 @@
#include "git2/odb_backend.h"
#include "repository.h"
-typedef struct {
- git_odb_backend base;
- int position;
-} fake_backend;
-
-static git_odb_backend *new_backend(int position)
-{
- fake_backend *b;
-
- b = git__malloc(sizeof(fake_backend));
- if (b == NULL)
- return NULL;
-
- memset(b, 0x0, sizeof(fake_backend));
- b->position = position;
- return (git_odb_backend *)b;
-}
-
-static int test_backend_sorting(git_odb *odb)
-{
- unsigned int i;
-
- for (i = 0; i < odb->backends.length; ++i) {
- fake_backend *internal = *((fake_backend **)git_vector_get(&odb->backends, i));
-
- if (internal == NULL)
- return GIT_ERROR;
-
- if (internal->position != (int)i)
- return GIT_ERROR;
- }
-
- return GIT_SUCCESS;
-}
-
-BEGIN_TEST(odb0, "assure that ODB backends are properly sorted")
- git_odb *odb;
- must_pass(git_odb_new(&odb));
- must_pass(git_odb_add_backend(odb, new_backend(0), 5));
- must_pass(git_odb_add_backend(odb, new_backend(2), 3));
- must_pass(git_odb_add_backend(odb, new_backend(1), 4));
- must_pass(git_odb_add_backend(odb, new_backend(3), 1));
- must_pass(test_backend_sorting(odb));
- git_odb_close(odb);
-END_TEST
-
-BEGIN_TEST(odb1, "assure that alternate backends are properly sorted")
- git_odb *odb;
- must_pass(git_odb_new(&odb));
- must_pass(git_odb_add_backend(odb, new_backend(0), 5));
- must_pass(git_odb_add_backend(odb, new_backend(2), 3));
- must_pass(git_odb_add_backend(odb, new_backend(1), 4));
- must_pass(git_odb_add_backend(odb, new_backend(3), 1));
- must_pass(git_odb_add_alternate(odb, new_backend(4), 5));
- must_pass(git_odb_add_alternate(odb, new_backend(6), 3));
- must_pass(git_odb_add_alternate(odb, new_backend(5), 4));
- must_pass(git_odb_add_alternate(odb, new_backend(7), 1));
- must_pass(test_backend_sorting(odb));
- git_odb_close(odb);
-END_TEST
-
-
-#define STANDARD_REPOSITORY 0
-#define BARE_REPOSITORY 1
-
-static int ensure_repository_init(
- const char *working_directory,
- int repository_kind,
- const char *expected_path_index,
- const char *expected_path_repository,
- const char *expected_working_directory)
-{
- char path_odb[GIT_PATH_MAX];
- git_repository *repo;
-
- if (git_futils_isdir(working_directory) == GIT_SUCCESS)
- return GIT_ERROR;
-
- git_path_join(path_odb, expected_path_repository, GIT_OBJECTS_DIR);
-
- if (git_repository_init(&repo, working_directory, repository_kind) < GIT_SUCCESS)
- return GIT_ERROR;
-
- if (repo->path_workdir != NULL || expected_working_directory != NULL) {
- if (git__suffixcmp(repo->path_workdir, expected_working_directory) != 0)
- goto cleanup;
- }
-
- if (git__suffixcmp(repo->path_odb, path_odb) != 0)
- goto cleanup;
-
- if (git__suffixcmp(repo->path_repository, expected_path_repository) != 0)
- goto cleanup;
-
- if (repo->path_index != NULL || expected_path_index != NULL) {
- if (git__suffixcmp(repo->path_index, expected_path_index) != 0)
- goto cleanup;
-
-#ifdef GIT_WIN32
- if ((GetFileAttributes(repo->path_repository) & FILE_ATTRIBUTE_HIDDEN) == 0)
- goto cleanup;
-#endif
-
- if (git_repository_is_bare(repo) == 1)
- goto cleanup;
- } else if (git_repository_is_bare(repo) == 0)
- goto cleanup;
-
- if (git_repository_is_empty(repo) == 0)
- goto cleanup;
-
- git_repository_free(repo);
- git_futils_rmdir_r(working_directory, 1);
-
- return GIT_SUCCESS;
-
-cleanup:
- git_repository_free(repo);
- git_futils_rmdir_r(working_directory, 1);
- return GIT_ERROR;
-}
-
-BEGIN_TEST(init0, "initialize a standard repo")
- char path_index[GIT_PATH_MAX], path_repository[GIT_PATH_MAX];
-
- git_path_join(path_repository, TEMP_REPO_FOLDER, GIT_DIR);
- git_path_join(path_index, path_repository, GIT_INDEX_FILE);
-
- must_pass(ensure_repository_init(TEMP_REPO_FOLDER, STANDARD_REPOSITORY, path_index, path_repository, TEMP_REPO_FOLDER));
- must_pass(ensure_repository_init(TEMP_REPO_FOLDER_NS, STANDARD_REPOSITORY, path_index, path_repository, TEMP_REPO_FOLDER));
-END_TEST
-
-BEGIN_TEST(init1, "initialize a bare repo")
- char path_repository[GIT_PATH_MAX];
-
- git_path_join(path_repository, TEMP_REPO_FOLDER, "");
-
- must_pass(ensure_repository_init(TEMP_REPO_FOLDER, BARE_REPOSITORY, NULL, path_repository, NULL));
- must_pass(ensure_repository_init(TEMP_REPO_FOLDER_NS, BARE_REPOSITORY, NULL, path_repository, NULL));
-END_TEST
-
-BEGIN_TEST(init2, "Initialize and open a bare repo with a relative path escaping out of the current working directory")
- char path_repository[GIT_PATH_MAX];
- char current_workdir[GIT_PATH_MAX];
- const mode_t mode = 0777;
- git_repository* repo;
-
- must_pass(p_getcwd(current_workdir, sizeof(current_workdir)));
-
- git_path_join(path_repository, TEMP_REPO_FOLDER, "a/b/c/");
- must_pass(git_futils_mkdir_r(path_repository, mode));
-
- must_pass(chdir(path_repository));
-
- must_pass(git_repository_init(&repo, "../d/e.git", 1));
- must_pass(git__suffixcmp(repo->path_repository, "/a/b/d/e.git/"));
-
- git_repository_free(repo);
-
- must_pass(git_repository_open(&repo, "../d/e.git"));
-
- git_repository_free(repo);
-
- must_pass(chdir(current_workdir));
- must_pass(git_futils_rmdir_r(TEMP_REPO_FOLDER, 1));
-END_TEST
-
#define EMPTY_BARE_REPOSITORY_FOLDER TEST_RESOURCES "/empty_bare.git/"
-BEGIN_TEST(open0, "Open a bare repository that has just been initialized by git")
- git_repository *repo;
-
- must_pass(copydir_recurs(EMPTY_BARE_REPOSITORY_FOLDER, TEMP_REPO_FOLDER));
- must_pass(remove_placeholders(TEMP_REPO_FOLDER, "dummy-marker.txt"));
-
- must_pass(git_repository_open(&repo, TEMP_REPO_FOLDER));
- must_be_true(git_repository_path(repo, GIT_REPO_PATH) != NULL);
- must_be_true(git_repository_path(repo, GIT_REPO_PATH_WORKDIR) == NULL);
-
- git_repository_free(repo);
- must_pass(git_futils_rmdir_r(TEMP_REPO_FOLDER, 1));
-END_TEST
-
-BEGIN_TEST(open1, "Open a standard repository that has just been initialized by git")
- git_repository *repo;
-
- must_pass(copydir_recurs(EMPTY_REPOSITORY_FOLDER, TEST_STD_REPO_FOLDER));
- must_pass(remove_placeholders(TEST_STD_REPO_FOLDER, "dummy-marker.txt"));
-
- must_pass(git_repository_open(&repo, TEST_STD_REPO_FOLDER));
- must_be_true(git_repository_path(repo, GIT_REPO_PATH) != NULL);
- must_be_true(git_repository_path(repo, GIT_REPO_PATH_WORKDIR) != NULL);
-
- git_repository_free(repo);
- must_pass(git_futils_rmdir_r(TEMP_REPO_FOLDER, 1));
-END_TEST
-
-
-BEGIN_TEST(open2, "Open a bare repository with a relative path escaping out of the current working directory")
- char new_current_workdir[GIT_PATH_MAX];
- char current_workdir[GIT_PATH_MAX];
- char path_repository[GIT_PATH_MAX];
-
- const mode_t mode = 0777;
- git_repository* repo;
-
- /* Setup the repository to open */
- must_pass(p_getcwd(current_workdir, sizeof(current_workdir)));
- strcpy(path_repository, current_workdir);
- git_path_join_n(path_repository, 3, path_repository, TEMP_REPO_FOLDER, "a/d/e.git");
- must_pass(copydir_recurs(REPOSITORY_FOLDER, path_repository));
-
- /* Change the current working directory */
- git_path_join(new_current_workdir, TEMP_REPO_FOLDER, "a/b/c/");
- must_pass(git_futils_mkdir_r(new_current_workdir, mode));
- must_pass(chdir(new_current_workdir));
-
- must_pass(git_repository_open(&repo, "../../d/e.git"));
-
- git_repository_free(repo);
-
- must_pass(chdir(current_workdir));
- must_pass(git_futils_rmdir_r(TEMP_REPO_FOLDER, 1));
-END_TEST
-
-BEGIN_TEST(empty0, "test if a repository is empty or not")
-
- git_repository *repo_empty, *repo_normal;
-
- must_pass(git_repository_open(&repo_normal, REPOSITORY_FOLDER));
- must_be_true(git_repository_is_empty(repo_normal) == 0);
- git_repository_free(repo_normal);
-
- must_pass(git_repository_open(&repo_empty, EMPTY_BARE_REPOSITORY_FOLDER));
- must_be_true(git_repository_is_empty(repo_empty) == 1);
- git_repository_free(repo_empty);
-END_TEST
-
-BEGIN_TEST(detached0, "test if HEAD is detached")
- git_repository *repo;
- git_reference *ref;
- git_oid oid;
-
- must_pass(git_repository_open(&repo, REPOSITORY_FOLDER));
-
- must_be_true(git_repository_head_detached(repo) == 0);
-
- /* detach the HEAD */
- git_oid_fromstr(&oid, "c47800c7266a2be04c571c04d5a6614691ea99bd");
- must_pass(git_reference_create_oid(&ref, repo, "HEAD", &oid, 1));
- must_be_true(git_repository_head_detached(repo) == 1);
-
- /* take the reop back to it's original state */
- must_pass(git_reference_create_symbolic(&ref, repo, "HEAD", "refs/heads/master", 1));
- must_be_true(git_repository_head_detached(repo) == 0);
-
- git_repository_free(repo);
-
- git_reference_free(ref);
-END_TEST
-
-BEGIN_TEST(orphan0, "test if HEAD is orphan")
- git_repository *repo;
- git_reference *ref;
-
- must_pass(git_repository_open(&repo, REPOSITORY_FOLDER));
-
- must_be_true(git_repository_head_orphan(repo) == 0);
-
- /* orphan HEAD */
- must_pass(git_reference_create_symbolic(&ref, repo, "HEAD", "refs/heads/orphan", 1));
- must_be_true(git_repository_head_orphan(repo) == 1);
-
- /* take the reop back to it's original state */
- must_pass(git_reference_create_symbolic(&ref, repo, "HEAD", "refs/heads/master", 1));
- must_be_true(git_repository_head_orphan(repo) == 0);
-
- git_repository_free(repo);
-
- git_reference_free(ref);
-END_TEST
-
#define DISCOVER_FOLDER TEMP_REPO_FOLDER "discover.git"
#define SUB_REPOSITORY_FOLDER_NAME "sub_repo"
@@ -449,17 +169,6 @@ BEGIN_TEST(discover0, "test discover")
END_TEST
BEGIN_SUITE(repository)
- ADD_TEST(odb0);
- ADD_TEST(odb1);
- ADD_TEST(init0);
- ADD_TEST(init1);
- ADD_TEST(init2);
- ADD_TEST(open0);
- ADD_TEST(open1);
- ADD_TEST(open2);
- ADD_TEST(empty0);
- ADD_TEST(detached0);
- ADD_TEST(orphan0);
ADD_TEST(discover0);
END_SUITE
diff --git a/tests/t15-config.c b/tests/t15-config.c
deleted file mode 100644
index 9f0deb3e3..000000000
--- a/tests/t15-config.c
+++ /dev/null
@@ -1,358 +0,0 @@
-/*
- * This file is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License, version 2,
- * as published by the Free Software Foundation.
- *
- * In addition to the permissions in the GNU General Public License,
- * the authors give you unlimited permission to link the compiled
- * version of this file into combinations with other programs,
- * and to distribute those combinations without any restriction
- * coming from the use of this file. (The General Public License
- * restrictions do apply in other respects; for example, they cover
- * modification of the file, and distribution when not linked into
- * a combined executable.)
- *
- * This file is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; see the file COPYING. If not, write to
- * the Free Software Foundation, 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-#include "test_lib.h"
-#include "test_helpers.h"
-
-#include <git2.h>
-#include <posix.h>
-#include "filebuf.h"
-
-#define CONFIG_BASE TEST_RESOURCES "/config"
-#define GLOBAL_CONFIG CONFIG_BASE "/.gitconfig"
-
-/*
- * This one is so we know the code isn't completely broken
- */
-BEGIN_TEST(config0, "read a simple configuration")
- git_config *cfg;
- int32_t i;
-
- must_pass(git_config_open_ondisk(&cfg, CONFIG_BASE "/config0"));
- must_pass(git_config_get_int32(cfg, "core.repositoryformatversion", &i));
- must_be_true(i == 0);
- must_pass(git_config_get_bool(cfg, "core.filemode", &i));
- must_be_true(i == 1);
- must_pass(git_config_get_bool(cfg, "core.bare", &i));
- must_be_true(i == 0);
- must_pass(git_config_get_bool(cfg, "core.logallrefupdates", &i));
- must_be_true(i == 1);
-
- git_config_free(cfg);
-END_TEST
-
-/*
- * [this "that"] and [this "That] are different namespaces. Make sure
- * each returns the correct one.
- */
-BEGIN_TEST(config1, "case sensitivity")
- git_config *cfg;
- int i;
- const char *str;
-
- must_pass(git_config_open_ondisk(&cfg, CONFIG_BASE "/config1"));
-
- must_pass(git_config_get_string(cfg, "this.that.other", &str));
- must_be_true(!strcmp(str, "true"));
- must_pass(git_config_get_string(cfg, "this.That.other", &str));
- must_be_true(!strcmp(str, "yes"));
-
- must_pass(git_config_get_bool(cfg, "this.that.other", &i));
- must_be_true(i == 1);
- must_pass(git_config_get_bool(cfg, "this.That.other", &i));
- must_be_true(i == 1);
-
- /* This one doesn't exist */
- must_fail(git_config_get_bool(cfg, "this.thaT.other", &i));
-
- git_config_free(cfg);
-END_TEST
-
-/*
- * If \ is the last non-space character on the line, we read the next
- * one, separating each line with SP.
- */
-BEGIN_TEST(config2, "parse a multiline value")
- git_config *cfg;
- const char *str;
-
- must_pass(git_config_open_ondisk(&cfg, CONFIG_BASE "/config2"));
-
- must_pass(git_config_get_string(cfg, "this.That.and", &str));
- must_be_true(!strcmp(str, "one one one two two three three"));
-
- git_config_free(cfg);
-END_TEST
-
-/*
- * This kind of subsection declaration is case-insensitive
- */
-BEGIN_TEST(config3, "parse a [section.subsection] header")
- git_config *cfg;
- const char *str;
-
- must_pass(git_config_open_ondisk(&cfg, CONFIG_BASE "/config3"));
-
- must_pass(git_config_get_string(cfg, "section.subsection.var", &str));
- must_be_true(!strcmp(str, "hello"));
-
- /* The subsection is transformed to lower-case */
- must_fail(git_config_get_string(cfg, "section.subSectIon.var", &str));
-
- git_config_free(cfg);
-END_TEST
-
-BEGIN_TEST(config4, "a variable name on its own is valid")
- git_config *cfg;
-const char *str;
-int i;
-
- must_pass(git_config_open_ondisk(&cfg, CONFIG_BASE "/config4"));
-
- must_pass(git_config_get_string(cfg, "some.section.variable", &str));
- must_be_true(str == NULL);
-
- must_pass(git_config_get_bool(cfg, "some.section.variable", &i));
- must_be_true(i == 1);
-
-
- git_config_free(cfg);
-END_TEST
-
-BEGIN_TEST(config5, "test number suffixes")
- git_config *cfg;
- int64_t i;
-
- must_pass(git_config_open_ondisk(&cfg, CONFIG_BASE "/config5"));
-
- must_pass(git_config_get_int64(cfg, "number.simple", &i));
- must_be_true(i == 1);
-
- must_pass(git_config_get_int64(cfg, "number.k", &i));
- must_be_true(i == 1 * 1024);
-
- must_pass(git_config_get_int64(cfg, "number.kk", &i));
- must_be_true(i == 1 * 1024);
-
- must_pass(git_config_get_int64(cfg, "number.m", &i));
- must_be_true(i == 1 * 1024 * 1024);
-
- must_pass(git_config_get_int64(cfg, "number.mm", &i));
- must_be_true(i == 1 * 1024 * 1024);
-
- must_pass(git_config_get_int64(cfg, "number.g", &i));
- must_be_true(i == 1 * 1024 * 1024 * 1024);
-
- must_pass(git_config_get_int64(cfg, "number.gg", &i));
- must_be_true(i == 1 * 1024 * 1024 * 1024);
-
- git_config_free(cfg);
-END_TEST
-
-BEGIN_TEST(config6, "test blank lines")
- git_config *cfg;
- int i;
-
- must_pass(git_config_open_ondisk(&cfg, CONFIG_BASE "/config6"));
-
- must_pass(git_config_get_bool(cfg, "valid.subsection.something", &i));
- must_be_true(i == 1);
-
- must_pass(git_config_get_bool(cfg, "something.else.something", &i));
- must_be_true(i == 0);
-
- git_config_free(cfg);
-END_TEST
-
-BEGIN_TEST(config7, "test for invalid ext headers")
- git_config *cfg;
-
- must_fail(git_config_open_ondisk(&cfg, CONFIG_BASE "/config7"));
-
-END_TEST
-
-BEGIN_TEST(config8, "don't fail on empty files")
- git_config *cfg;
-
- must_pass(git_config_open_ondisk(&cfg, CONFIG_BASE "/config8"));
-
- git_config_free(cfg);
-END_TEST
-
-BEGIN_TEST(config9, "replace a value")
- git_config *cfg;
- int i;
- int64_t l, expected = +9223372036854775803;
-
- /* By freeing the config, we make sure we flush the values */
- must_pass(git_config_open_ondisk(&cfg, CONFIG_BASE "/config9"));
- must_pass(git_config_set_int32(cfg, "core.dummy", 5));
- git_config_free(cfg);
-
- must_pass(git_config_open_ondisk(&cfg, CONFIG_BASE "/config9"));
- must_pass(git_config_get_int32(cfg, "core.dummy", &i));
- must_be_true(i == 5);
- git_config_free(cfg);
-
- must_pass(git_config_open_ondisk(&cfg, CONFIG_BASE "/config9"));
- must_pass(git_config_set_int32(cfg, "core.dummy", 1));
- git_config_free(cfg);
-
- must_pass(git_config_open_ondisk(&cfg, CONFIG_BASE "/config9"));
- must_pass(git_config_set_int64(cfg, "core.verylong", expected));
- git_config_free(cfg);
-
- must_pass(git_config_open_ondisk(&cfg, CONFIG_BASE "/config9"));
- must_pass(git_config_get_int64(cfg, "core.verylong", &l));
- must_be_true(l == expected);
- git_config_free(cfg);
-
- must_pass(git_config_open_ondisk(&cfg, CONFIG_BASE "/config9"));
- must_fail(git_config_get_int32(cfg, "core.verylong", &i));
- git_config_free(cfg);
-
- must_pass(git_config_open_ondisk(&cfg, CONFIG_BASE "/config9"));
- must_pass(git_config_set_int64(cfg, "core.verylong", 1));
- git_config_free(cfg);
-
-END_TEST
-
-BEGIN_TEST(config10, "a repo's config overrides the global config")
- git_repository *repo;
- git_config *cfg;
- int32_t version;
-
- must_pass(git_repository_open(&repo, REPOSITORY_FOLDER));
- must_pass(git_repository_config(&cfg, repo, GLOBAL_CONFIG, NULL));
- must_pass(git_config_get_int32(cfg, "core.repositoryformatversion", &version));
- must_be_true(version == 0);
- git_config_free(cfg);
- git_repository_free(repo);
-END_TEST
-
-BEGIN_TEST(config11, "fall back to the global config")
- git_repository *repo;
- git_config *cfg;
- int32_t num;
-
- must_pass(git_repository_open(&repo, REPOSITORY_FOLDER));
- must_pass(git_repository_config(&cfg, repo, GLOBAL_CONFIG, NULL));
- must_pass(git_config_get_int32(cfg, "core.something", &num));
- must_be_true(num == 2);
- git_config_free(cfg);
- git_repository_free(repo);
-END_TEST
-
-BEGIN_TEST(config12, "delete a value")
- git_config *cfg;
- int32_t i;
-
- /* By freeing the config, we make sure we flush the values */
- must_pass(git_config_open_ondisk(&cfg, CONFIG_BASE "/config9"));
- must_pass(git_config_set_int32(cfg, "core.dummy", 5));
- git_config_free(cfg);
-
- must_pass(git_config_open_ondisk(&cfg, CONFIG_BASE "/config9"));
- must_pass(git_config_delete(cfg, "core.dummy"));
- git_config_free(cfg);
-
- must_pass(git_config_open_ondisk(&cfg, CONFIG_BASE "/config9"));
- must_be_true(git_config_get_int32(cfg, "core.dummy", &i) == GIT_ENOTFOUND);
- must_pass(git_config_set_int32(cfg, "core.dummy", 1));
- git_config_free(cfg);
-END_TEST
-
-BEGIN_TEST(config13, "can't delete a non-existent value")
- git_config *cfg;
-
- /* By freeing the config, we make sure we flush the values */
- must_pass(git_config_open_ondisk(&cfg, CONFIG_BASE "/config9"));
- must_be_true(git_config_delete(cfg, "core.imaginary") == GIT_ENOTFOUND);
- git_config_free(cfg);
-END_TEST
-
-BEGIN_TEST(config14, "don't fail horribly if a section header is in the last line")
- git_config *cfg;
-
- /* By freeing the config, we make sure we flush the values */
- must_pass(git_config_open_ondisk(&cfg, CONFIG_BASE "/config10"));
- git_config_free(cfg);
-END_TEST
-
-BEGIN_TEST(config15, "add a variable in an existing section")
- git_config *cfg;
- int32_t i;
-
- /* By freeing the config, we make sure we flush the values */
- must_pass(git_config_open_ondisk(&cfg, CONFIG_BASE "/config10"));
- must_pass(git_config_set_int32(cfg, "empty.tmp", 5));
- must_pass(git_config_get_int32(cfg, "empty.tmp", &i));
- must_be_true(i == 5);
- must_pass(git_config_delete(cfg, "empty.tmp"));
- git_config_free(cfg);
-END_TEST
-
-BEGIN_TEST(config16, "add a variable in a new section")
- git_config *cfg;
- int32_t i;
- git_filebuf buf = GIT_FILEBUF_INIT;
-
- /* By freeing the config, we make sure we flush the values */
- must_pass(git_config_open_ondisk(&cfg, CONFIG_BASE "/config10"));
- must_pass(git_config_set_int32(cfg, "section.tmp", 5));
- must_pass(git_config_get_int32(cfg, "section.tmp", &i));
- must_be_true(i == 5);
- must_pass(git_config_delete(cfg, "section.tmp"));
- git_config_free(cfg);
-
- /* As the section wasn't removed, owerwrite the file */
- must_pass(git_filebuf_open(&buf, CONFIG_BASE "/config10", 0));
- must_pass(git_filebuf_write(&buf, "[empty]\n", strlen("[empty]\n")));
- must_pass(git_filebuf_commit(&buf, 0666));
-END_TEST
-
-BEGIN_TEST(config17, "prefixes aren't broken")
- git_config *cfg;
- const char *str;
-
- must_pass(git_config_open_ondisk(&cfg, CONFIG_BASE "/config9"));
- must_pass(git_config_get_string(cfg, "remote.ab.url", &str));
- must_be_true(strcmp(str, "http://example.com/git/ab") == 0);
-
- must_pass(git_config_get_string(cfg, "remote.abba.url", &str));
- must_be_true(strcmp(str, "http://example.com/git/abba") == 0);
-
- git_config_free(cfg);
-END_TEST
-
-BEGIN_SUITE(config)
- ADD_TEST(config0);
- ADD_TEST(config1);
- ADD_TEST(config2);
- ADD_TEST(config3);
- ADD_TEST(config4);
- ADD_TEST(config5);
- ADD_TEST(config6);
- ADD_TEST(config7);
- ADD_TEST(config8);
- ADD_TEST(config9);
- ADD_TEST(config10);
- ADD_TEST(config11);
- ADD_TEST(config12);
- ADD_TEST(config13);
- ADD_TEST(config14);
- ADD_TEST(config15);
- ADD_TEST(config16);
- ADD_TEST(config17);
-END_SUITE
diff --git a/tests/t16-remotes.c b/tests/t16-remotes.c
deleted file mode 100644
index ac98bdf5e..000000000
--- a/tests/t16-remotes.c
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * This file is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License, version 2,
- * as published by the Free Software Foundation.
- *
- * In addition to the permissions in the GNU General Public License,
- * the authors give you unlimited permission to link the compiled
- * version of this file into combinations with other programs,
- * and to distribute those combinations without any restriction
- * coming from the use of this file. (The General Public License
- * restrictions do apply in other respects; for example, they cover
- * modification of the file, and distribution when not linked into
- * a combined executable.)
- *
- * This file is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; see the file COPYING. If not, write to
- * the Free Software Foundation, 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-#include "test_lib.h"
-#include "test_helpers.h"
-
-#include <git2.h>
-#include <posix.h>
-
-BEGIN_TEST(remotes0, "remote parsing works")
- git_remote *remote;
- git_repository *repo;
- git_config *cfg;
-
- must_pass(git_repository_open(&repo, REPOSITORY_FOLDER));
- must_pass(git_repository_config(&cfg, repo, NULL, NULL));
- must_pass(git_remote_get(&remote, cfg, "test"));
- must_be_true(!strcmp(git_remote_name(remote), "test"));
- must_be_true(!strcmp(git_remote_url(remote), "git://github.com/libgit2/libgit2"));
-
- git_remote_free(remote);
- git_config_free(cfg);
- git_repository_free(repo);
-END_TEST
-
-BEGIN_TEST(refspec0, "remote with refspec works")
- git_remote *remote;
- git_repository *repo;
- git_config *cfg;
- const git_refspec *refspec = NULL;
-
- must_pass(git_repository_open(&repo, REPOSITORY_FOLDER));
- must_pass(git_repository_config(&cfg, repo, NULL, NULL));
- must_pass(git_remote_get(&remote, cfg, "test"));
- refspec = git_remote_fetchspec(remote);
- must_be_true(refspec != NULL);
- must_be_true(!strcmp(git_refspec_src(refspec), "refs/heads/*"));
- must_be_true(!strcmp(git_refspec_dst(refspec), "refs/remotes/test/*"));
- git_remote_free(remote);
- git_config_free(cfg);
- git_repository_free(repo);
-END_TEST
-
-BEGIN_TEST(refspec1, "remote fnmatch works as expected")
- git_remote *remote;
- git_repository *repo;
- git_config *cfg;
- const git_refspec *refspec = NULL;
-
- must_pass(git_repository_open(&repo, REPOSITORY_FOLDER));
- must_pass(git_repository_config(&cfg, repo, NULL, NULL));
- must_pass(git_remote_get(&remote, cfg, "test"));
- refspec = git_remote_fetchspec(remote);
- must_be_true(refspec != NULL);
- must_pass(git_refspec_src_match(refspec, "refs/heads/master"));
- must_pass(git_refspec_src_match(refspec, "refs/heads/multi/level/branch"));
- git_remote_free(remote);
- git_config_free(cfg);
- git_repository_free(repo);
-END_TEST
-
-BEGIN_TEST(refspec2, "refspec transform")
- git_remote *remote;
- git_repository *repo;
- git_config *cfg;
- const git_refspec *refspec = NULL;
- char ref[1024] = {0};
-
- must_pass(git_repository_open(&repo, REPOSITORY_FOLDER));
- must_pass(git_repository_config(&cfg, repo, NULL, NULL));
- must_pass(git_remote_get(&remote, cfg, "test"));
- refspec = git_remote_fetchspec(remote);
- must_be_true(refspec != NULL);
- must_pass(git_refspec_transform(ref, sizeof(ref), refspec, "refs/heads/master"));
- must_be_true(!strcmp(ref, "refs/remotes/test/master"));
- git_remote_free(remote);
- git_config_free(cfg);
- git_repository_free(repo);
-END_TEST
-
-BEGIN_SUITE(remotes)
- ADD_TEST(remotes0)
- ADD_TEST(refspec0)
- ADD_TEST(refspec1)
- ADD_TEST(refspec2)
-END_SUITE
diff --git a/tests/test_main.c b/tests/test_main.c
index 9961ffd6b..1ebb22299 100644
--- a/tests/test_main.c
+++ b/tests/test_main.c
@@ -33,7 +33,6 @@
DECLARE_SUITE(core);
DECLARE_SUITE(rawobjects);
-DECLARE_SUITE(objread);
DECLARE_SUITE(objwrite);
DECLARE_SUITE(commit);
DECLARE_SUITE(revwalk);
@@ -44,15 +43,12 @@ DECLARE_SUITE(tree);
DECLARE_SUITE(refs);
DECLARE_SUITE(repository);
DECLARE_SUITE(threads);
-DECLARE_SUITE(config);
-DECLARE_SUITE(remotes);
DECLARE_SUITE(buffers);
DECLARE_SUITE(status);
static libgit2_suite suite_methods[]= {
SUITE_NAME(core),
SUITE_NAME(rawobjects),
- SUITE_NAME(objread),
SUITE_NAME(objwrite),
SUITE_NAME(commit),
SUITE_NAME(revwalk),
@@ -63,8 +59,6 @@ static libgit2_suite suite_methods[]= {
SUITE_NAME(refs),
SUITE_NAME(repository),
SUITE_NAME(threads),
- SUITE_NAME(config),
- SUITE_NAME(remotes),
SUITE_NAME(buffers),
SUITE_NAME(status),
};