mirror of
https://git.proxmox.com/git/libgit2
synced 2026-01-07 04:57:36 +00:00
Merge branch 'repo-ownership' into development
This commit is contained in:
commit
bb34a93621
@ -107,7 +107,7 @@ int main (int argc, char** argv)
|
||||
|
||||
// For proper memory management, close the object when you are done with it or it will leak
|
||||
// memory.
|
||||
git_odb_object_close(obj);
|
||||
git_odb_object_free(obj);
|
||||
|
||||
// #### Raw Object Writing
|
||||
|
||||
@ -167,12 +167,12 @@ int main (int argc, char** argv)
|
||||
git_commit_parent(&parent, commit, p);
|
||||
git_oid_fmt(out, git_commit_id(parent));
|
||||
printf("Parent: %s\n", out);
|
||||
git_commit_close(parent);
|
||||
git_commit_free(parent);
|
||||
}
|
||||
|
||||
// Don't forget to close the object to prevent memory leaks. You will have to do this for
|
||||
// all the objects you open and parse.
|
||||
git_commit_close(commit);
|
||||
git_commit_free(commit);
|
||||
|
||||
// #### Writing Commits
|
||||
//
|
||||
@ -243,7 +243,7 @@ int main (int argc, char** argv)
|
||||
tmessage = git_tag_message(tag); // "tag message\n"
|
||||
printf("Tag Message: %s\n", tmessage);
|
||||
|
||||
git_commit_close(commit);
|
||||
git_commit_free(commit);
|
||||
|
||||
// #### Tree Parsing
|
||||
// [Tree parsing][tp] is a bit different than the other objects, in that we have a subtype which is the
|
||||
@ -276,7 +276,7 @@ int main (int argc, char** argv)
|
||||
git_tree_entry_2object(&objt, repo, entry); // blob
|
||||
|
||||
// Remember to close the looked-up object once you are done using it
|
||||
git_object_close(objt);
|
||||
git_object_free(objt);
|
||||
|
||||
// #### Blob Parsing
|
||||
//
|
||||
@ -340,7 +340,7 @@ int main (int argc, char** argv)
|
||||
cmsg = git_commit_message(wcommit);
|
||||
cauth = git_commit_author(wcommit);
|
||||
printf("%s (%s)\n", cmsg, cauth->email);
|
||||
git_commit_close(wcommit);
|
||||
git_commit_free(wcommit);
|
||||
}
|
||||
|
||||
// Like the other objects, be sure to free the revwalker when you're done to prevent memory leaks.
|
||||
|
||||
@ -1,17 +1,8 @@
|
||||
default: all
|
||||
|
||||
# If you've installed libgit2 to a non-standard location, you can use
|
||||
# these lines to make pkg-config find it.
|
||||
|
||||
#LIBGIT2_PATH ?= $(HOME)/staging/libgit2/lib DEPS =
|
||||
#$(shell PKG_CONFIG_PATH=$(LIBGIT2_PATH)/pkgconfig pkg-config --cflags
|
||||
#--libs libgit2)
|
||||
|
||||
DEPS = $(shell pkg-config --cflags --libs libgit2)
|
||||
|
||||
CC = gcc
|
||||
CFLAGS += -g
|
||||
CFLAGS += $(DEPS)
|
||||
CFLAGS += -I../../include -L../../ -lgit2
|
||||
|
||||
OBJECTS = \
|
||||
git2.o \
|
||||
|
||||
@ -4,23 +4,6 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
static void show_refs(git_headarray *refs)
|
||||
{
|
||||
int i;
|
||||
git_remote_head *head;
|
||||
|
||||
if(refs->len == 0)
|
||||
puts("Everything up-to-date");
|
||||
|
||||
for(i = 0; i < refs->len; ++i){
|
||||
char oid[GIT_OID_HEXSZ + 1] = {0};
|
||||
char *havewant;
|
||||
head = refs->heads[i];
|
||||
git_oid_fmt(oid, &head->oid);
|
||||
printf("%s\t%s\n", oid, head->name);
|
||||
}
|
||||
}
|
||||
|
||||
static int rename_packfile(char *packname, git_indexer *idx)
|
||||
{
|
||||
char path[GIT_PATH_MAX], oid[GIT_OID_HEXSZ + 1], *slash;
|
||||
@ -50,20 +33,14 @@ static int rename_packfile(char *packname, git_indexer *idx)
|
||||
int fetch(git_repository *repo, int argc, char **argv)
|
||||
{
|
||||
git_remote *remote = NULL;
|
||||
git_config *cfg = NULL;
|
||||
git_indexer *idx = NULL;
|
||||
git_indexer_stats stats;
|
||||
int error;
|
||||
char *packname = NULL;
|
||||
|
||||
// Load the repository's configuration
|
||||
error = git_repository_config(&cfg, repo, NULL, NULL);
|
||||
if (error < GIT_SUCCESS)
|
||||
return error;
|
||||
|
||||
// Get the remote and connect to it
|
||||
printf("Fetching %s\n", argv[1]);
|
||||
error = git_remote_get(&remote, cfg, argv[1]);
|
||||
error = git_remote_new(&remote, repo, argv[1], NULL);
|
||||
if (error < GIT_SUCCESS)
|
||||
return error;
|
||||
|
||||
@ -71,13 +48,6 @@ int fetch(git_repository *repo, int argc, char **argv)
|
||||
if (error < GIT_SUCCESS)
|
||||
return error;
|
||||
|
||||
// Perform the packfile negotiation. This is where the two ends
|
||||
// figure out the minimal amount of data that should be transmitted
|
||||
// to bring the repository up-to-date
|
||||
error = git_remote_negotiate(remote);
|
||||
if (error < GIT_SUCCESS)
|
||||
return error;
|
||||
|
||||
// Download the packfile from the server. As we don't know its hash
|
||||
// yet, it will get a temporary filename
|
||||
error = git_remote_download(&packname, remote);
|
||||
|
||||
@ -4,31 +4,22 @@
|
||||
#include <string.h>
|
||||
#include "common.h"
|
||||
|
||||
static void show_refs(git_headarray *refs)
|
||||
static int show_ref__cb(git_remote_head *head, void *payload)
|
||||
{
|
||||
int i;
|
||||
git_remote_head *head;
|
||||
|
||||
// Take each head that the remote has advertised, store the string
|
||||
// representation of the OID in a buffer and print it
|
||||
|
||||
for(i = 0; i < refs->len; ++i){
|
||||
char oid[GIT_OID_HEXSZ + 1] = {0};
|
||||
head = refs->heads[i];
|
||||
git_oid_fmt(oid, &head->oid);
|
||||
printf("%s\t%s\n", oid, head->name);
|
||||
}
|
||||
char oid[GIT_OID_HEXSZ + 1] = {0};
|
||||
git_oid_fmt(oid, &head->oid);
|
||||
printf("%s\t%s\n", oid, head->name);
|
||||
return GIT_SUCCESS;
|
||||
}
|
||||
|
||||
int use_unnamed(git_repository *repo, const char *url)
|
||||
{
|
||||
git_remote *remote = NULL;
|
||||
git_headarray refs;
|
||||
int error;
|
||||
|
||||
// Create an instance of a remote from the URL. The transport to use
|
||||
// is detected from the URL
|
||||
error = git_remote_new(&remote, repo, url);
|
||||
error = git_remote_new(&remote, repo, url, NULL);
|
||||
if (error < GIT_SUCCESS)
|
||||
goto cleanup;
|
||||
|
||||
@ -39,32 +30,20 @@ int use_unnamed(git_repository *repo, const char *url)
|
||||
goto cleanup;
|
||||
|
||||
// With git_remote_ls we can retrieve the advertised heads
|
||||
error = git_remote_ls(remote, &refs);
|
||||
if (error < GIT_SUCCESS)
|
||||
goto cleanup;
|
||||
|
||||
show_refs(&refs);
|
||||
error = git_remote_ls(remote, &show_ref__cb, NULL);
|
||||
|
||||
cleanup:
|
||||
git_remote_free(remote);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
int use_remote(git_repository *repo, char *name)
|
||||
{
|
||||
git_remote *remote = NULL;
|
||||
git_config *cfg = NULL;
|
||||
git_headarray refs;
|
||||
int error;
|
||||
|
||||
// Load the local configuration for the repository
|
||||
error = git_repository_config(&cfg, repo, NULL, NULL);
|
||||
if (error < GIT_SUCCESS)
|
||||
return error;
|
||||
|
||||
// Find the remote by name
|
||||
error = git_remote_get(&remote, cfg, name);
|
||||
error = git_remote_load(&remote, repo, name);
|
||||
if (error < GIT_SUCCESS)
|
||||
goto cleanup;
|
||||
|
||||
@ -72,15 +51,10 @@ int use_remote(git_repository *repo, char *name)
|
||||
if (error < GIT_SUCCESS)
|
||||
goto cleanup;
|
||||
|
||||
error = git_remote_ls(remote, &refs);
|
||||
if (error < GIT_SUCCESS)
|
||||
goto cleanup;
|
||||
|
||||
show_refs(&refs);
|
||||
error = git_remote_ls(remote, &show_ref__cb, NULL);
|
||||
|
||||
cleanup:
|
||||
git_remote_free(remote);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
@ -89,8 +63,6 @@ cleanup:
|
||||
|
||||
int ls_remote(git_repository *repo, int argc, char **argv)
|
||||
{
|
||||
git_headarray heads;
|
||||
git_remote_head *head;
|
||||
int error, i;
|
||||
|
||||
/* If there's a ':' in the name, assume it's an URL */
|
||||
|
||||
@ -38,7 +38,6 @@
|
||||
|
||||
#include "git2/refspec.h"
|
||||
#include "git2/net.h"
|
||||
#include "git2/transport.h"
|
||||
#include "git2/status.h"
|
||||
#include "git2/indexer.h"
|
||||
|
||||
|
||||
@ -54,7 +54,7 @@ GIT_INLINE(int) git_blob_lookup_prefix(git_blob **blob, git_repository *repo, co
|
||||
/**
|
||||
* Close an open blob
|
||||
*
|
||||
* This is a wrapper around git_object_close()
|
||||
* This is a wrapper around git_object_free()
|
||||
*
|
||||
* IMPORTANT:
|
||||
* It *is* necessary to call this method when you stop
|
||||
@ -63,9 +63,9 @@ GIT_INLINE(int) git_blob_lookup_prefix(git_blob **blob, git_repository *repo, co
|
||||
* @param blob the blob to close
|
||||
*/
|
||||
|
||||
GIT_INLINE(void) git_blob_close(git_blob *blob)
|
||||
GIT_INLINE(void) git_blob_free(git_blob *blob)
|
||||
{
|
||||
git_object_close((git_object *) blob);
|
||||
git_object_free((git_object *) blob);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -56,7 +56,7 @@ GIT_INLINE(int) git_commit_lookup_prefix(git_commit **commit, git_repository *re
|
||||
/**
|
||||
* Close an open commit
|
||||
*
|
||||
* This is a wrapper around git_object_close()
|
||||
* This is a wrapper around git_object_free()
|
||||
*
|
||||
* IMPORTANT:
|
||||
* It *is* necessary to call this method when you stop
|
||||
@ -65,9 +65,9 @@ GIT_INLINE(int) git_commit_lookup_prefix(git_commit **commit, git_repository *re
|
||||
* @param commit the commit to close
|
||||
*/
|
||||
|
||||
GIT_INLINE(void) git_commit_close(git_commit *commit)
|
||||
GIT_INLINE(void) git_commit_free(git_commit *commit)
|
||||
{
|
||||
git_object_close((git_object *) commit);
|
||||
git_object_free((git_object *) commit);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -30,6 +30,7 @@ GIT_BEGIN_DECL
|
||||
#define GIT_DIR_FETCH 0
|
||||
#define GIT_DIR_PUSH 1
|
||||
|
||||
|
||||
/**
|
||||
* Remote head description, given out on `ls` calls.
|
||||
*/
|
||||
@ -41,12 +42,9 @@ struct git_remote_head {
|
||||
};
|
||||
|
||||
/**
|
||||
* Array of remote heads
|
||||
* Callback for listing the remote heads
|
||||
*/
|
||||
struct git_headarray {
|
||||
unsigned int len;
|
||||
struct git_remote_head **heads;
|
||||
};
|
||||
typedef int (*git_headlist_cb)(git_remote_head *, void *);
|
||||
|
||||
/** @} */
|
||||
GIT_END_DECL
|
||||
|
||||
@ -24,7 +24,7 @@ GIT_BEGIN_DECL
|
||||
* Lookup a reference to one of the objects in a repostory.
|
||||
*
|
||||
* The generated reference is owned by the repository and
|
||||
* should be closed with the `git_object_close` method
|
||||
* should be closed with the `git_object_free` method
|
||||
* instead of free'd manually.
|
||||
*
|
||||
* The 'type' parameter must match the type of the object
|
||||
@ -56,7 +56,7 @@ GIT_EXTERN(int) git_object_lookup(
|
||||
* the prefix; otherwise the method will fail.
|
||||
*
|
||||
* The generated reference is owned by the repository and
|
||||
* should be closed with the `git_object_close` method
|
||||
* should be closed with the `git_object_free` method
|
||||
* instead of free'd manually.
|
||||
*
|
||||
* The 'type' parameter must match the type of the object
|
||||
@ -123,7 +123,7 @@ GIT_EXTERN(git_repository *) git_object_owner(const git_object *obj);
|
||||
*
|
||||
* @param object the object to close
|
||||
*/
|
||||
GIT_EXTERN(void) git_object_close(git_object *object);
|
||||
GIT_EXTERN(void) git_object_free(git_object *object);
|
||||
|
||||
/**
|
||||
* Convert an object type to it's string representation.
|
||||
|
||||
@ -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.
|
||||
@ -282,7 +282,7 @@ GIT_EXTERN(int) git_odb_hashfile(git_oid *out, const char *path, git_otype type)
|
||||
*
|
||||
* @param object object to close
|
||||
*/
|
||||
GIT_EXTERN(void) git_odb_object_close(git_odb_object *object);
|
||||
GIT_EXTERN(void) git_odb_object_free(git_odb_object *object);
|
||||
|
||||
/**
|
||||
* Return the OID of an ODB object
|
||||
|
||||
@ -10,6 +10,8 @@
|
||||
#include "common.h"
|
||||
#include "repository.h"
|
||||
#include "refspec.h"
|
||||
#include "net.h"
|
||||
|
||||
/**
|
||||
* @file git2/remote.h
|
||||
* @brief Git remote management functions
|
||||
@ -39,7 +41,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 +51,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 +59,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 +67,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 +75,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 +84,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 +97,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
|
||||
@ -107,7 +109,7 @@ GIT_EXTERN(int) git_remote_connect(struct git_remote *remote, int direction);
|
||||
* @param remote the remote
|
||||
* @return GIT_SUCCESS or an error code
|
||||
*/
|
||||
GIT_EXTERN(int) git_remote_ls(git_remote *remote, git_headarray *refs);
|
||||
GIT_EXTERN(int) git_remote_ls(git_remote *remote, git_headlist_cb list_cb, void *payload);
|
||||
|
||||
/**
|
||||
* Download the packfile
|
||||
@ -149,7 +151,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 +161,15 @@ 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);
|
||||
|
||||
/**
|
||||
* Return whether a string is a valid remote URL
|
||||
*
|
||||
* @param tranport the url to check
|
||||
* @param 1 if the url is valid, 0 otherwise
|
||||
*/
|
||||
GIT_EXTERN(int) git_remote_valid_url(const char *url);
|
||||
|
||||
/** @} */
|
||||
GIT_END_DECL
|
||||
|
||||
@ -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,137 +35,47 @@ 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
|
||||
* 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).
|
||||
*
|
||||
* @param repository pointer to the repo which will be opened
|
||||
* The method will automatically detect if the repository is bare
|
||||
* (if there is a repository).
|
||||
*
|
||||
* @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).
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* Note that after a repository is free'd, all the objects it has spawned
|
||||
* will still exist until they are manually closed by the user
|
||||
* with `git_object_close`, but accessing any of the attributes of
|
||||
* with `git_object_free`, but accessing any of the attributes of
|
||||
* an object without a backing repository will result in undefined
|
||||
* behavior
|
||||
*
|
||||
@ -188,7 +88,6 @@ GIT_EXTERN(void) git_repository_free(git_repository *repo);
|
||||
*
|
||||
* TODO:
|
||||
* - Reinit the repository
|
||||
* - Create config files
|
||||
*
|
||||
* @param repo_out pointer to the repo which will be created or reinitialized
|
||||
* @param path the path to the repository
|
||||
@ -247,31 +146,43 @@ 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
|
||||
* Get the path of this repository
|
||||
*
|
||||
* This is the path of the `.git` folder for normal repositories,
|
||||
* or of the repository itself for bare repositories.
|
||||
*
|
||||
* @param repo A repository object
|
||||
* @return the path to the repository
|
||||
*/
|
||||
typedef enum {
|
||||
GIT_REPO_PATH,
|
||||
GIT_REPO_PATH_INDEX,
|
||||
GIT_REPO_PATH_ODB,
|
||||
GIT_REPO_PATH_WORKDIR
|
||||
} git_repository_pathid;
|
||||
GIT_EXTERN(const char *) git_repository_path(git_repository *repo);
|
||||
|
||||
/**
|
||||
* Get one of the paths to the repository
|
||||
* Get the path of the working directory for this repository
|
||||
*
|
||||
* Possible values for `id`:
|
||||
* If the repository is bare, this function will always return
|
||||
* NULL.
|
||||
*
|
||||
* 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
|
||||
* @param repo A repository object
|
||||
* @return the path to the working dir, if it exists
|
||||
*/
|
||||
GIT_EXTERN(const char *) git_repository_path(git_repository *repo, git_repository_pathid id);
|
||||
GIT_EXTERN(const char *) git_repository_workdir(git_repository *repo);
|
||||
|
||||
/**
|
||||
* Set the path to the working directory for this repository
|
||||
*
|
||||
* The working directory doesn't need to be the same one
|
||||
* that contains the `.git` folder for this repository.
|
||||
*
|
||||
* If this repository is bare, setting its working directory
|
||||
* will turn it into a normal repository, capable of performing
|
||||
* all the common workdir operations (checkout, status, index
|
||||
* manipulation, etc).
|
||||
*
|
||||
* @param repo A repository object
|
||||
* @param workdir The path to a working directory
|
||||
* @return GIT_SUCCESS, or an error code
|
||||
*/
|
||||
GIT_EXTERN(int) git_repository_set_workdir(git_repository *repo, const char *workdir);
|
||||
|
||||
/**
|
||||
* Check if a repository is bare
|
||||
@ -282,52 +193,97 @@ 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
|
||||
* Get the configuration file for this 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`.
|
||||
* If a configuration file has not been set, the default
|
||||
* config set for the repository will be returned, including
|
||||
* global and system configurations (if they are available).
|
||||
*
|
||||
* The resulting `git_config` instance will query the files in the following
|
||||
* order:
|
||||
* The configuration file must be freed once it's no longer
|
||||
* being used by the user.
|
||||
*
|
||||
* - 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
|
||||
* @param out Pointer to store the loaded config file
|
||||
* @param repo A repository object
|
||||
* @return GIT_SUCCESS, or an error code
|
||||
*/
|
||||
|
||||
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_config(git_config **out, git_repository *repo);
|
||||
|
||||
/**
|
||||
* Automatically load the configuration files
|
||||
* Set the configuration file for this repository
|
||||
*
|
||||
* 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.
|
||||
* This configuration file will be used for all configuration
|
||||
* queries involving this repository.
|
||||
*
|
||||
* @param out the repository's configuration
|
||||
* @param repo the repository for which to get the config
|
||||
* The repository will keep a reference to the config file;
|
||||
* the user must still free the config after setting it
|
||||
* to the repository, or it will leak.
|
||||
*
|
||||
* @param repo A repository object
|
||||
* @param config A Config object
|
||||
*/
|
||||
GIT_EXTERN(int) git_repository_config_autoload(
|
||||
git_config **out,
|
||||
git_repository *repo);
|
||||
GIT_EXTERN(void) git_repository_set_config(git_repository *repo, git_config *config);
|
||||
|
||||
/**
|
||||
* Get the Object Database for this repository.
|
||||
*
|
||||
* If a custom ODB has not been set, the default
|
||||
* database for the repository will be returned (the one
|
||||
* located in `.git/objects`).
|
||||
*
|
||||
* The ODB must be freed once it's no longer being used by
|
||||
* the user.
|
||||
*
|
||||
* @param out Pointer to store the loaded ODB
|
||||
* @param repo A repository object
|
||||
* @return GIT_SUCCESS, or an error code
|
||||
*/
|
||||
GIT_EXTERN(int) git_repository_odb(git_odb **out, git_repository *repo);
|
||||
|
||||
/**
|
||||
* Set the Object Database for this repository
|
||||
*
|
||||
* The ODB will be used for all object-related operations
|
||||
* involving this repository.
|
||||
*
|
||||
* The repository will keep a reference to the ODB; the user
|
||||
* must still free the ODB object after setting it to the
|
||||
* repository, or it will leak.
|
||||
*
|
||||
* @param repo A repository object
|
||||
* @param odb An ODB object
|
||||
*/
|
||||
GIT_EXTERN(void) git_repository_set_odb(git_repository *repo, git_odb *odb);
|
||||
|
||||
/**
|
||||
* Get the Index file for this repository.
|
||||
*
|
||||
* If a custom index has not been set, the default
|
||||
* index for the repository will be returned (the one
|
||||
* located in `.git/index`).
|
||||
*
|
||||
* The index must be freed once it's no longer being used by
|
||||
* the user.
|
||||
*
|
||||
* @param out Pointer to store the loaded index
|
||||
* @param repo A repository object
|
||||
* @return GIT_SUCCESS, or an error code
|
||||
*/
|
||||
GIT_EXTERN(int) git_repository_index(git_index **out, git_repository *repo);
|
||||
|
||||
/**
|
||||
* Set the index file for this repository
|
||||
*
|
||||
* This index will be used for all index-related operations
|
||||
* involving this repository.
|
||||
*
|
||||
* The repository will keep a reference to the index file;
|
||||
* the user must still free the index after setting it
|
||||
* to the repository, or it will leak.
|
||||
*
|
||||
* @param repo A repository object
|
||||
* @param index An index object
|
||||
*/
|
||||
GIT_EXTERN(void) git_repository_set_index(git_repository *repo, git_index *index);
|
||||
|
||||
/** @} */
|
||||
GIT_END_DECL
|
||||
|
||||
@ -54,7 +54,7 @@ GIT_INLINE(int) git_tag_lookup_prefix(git_tag **tag, git_repository *repo, const
|
||||
/**
|
||||
* Close an open tag
|
||||
*
|
||||
* This is a wrapper around git_object_close()
|
||||
* This is a wrapper around git_object_free()
|
||||
*
|
||||
* IMPORTANT:
|
||||
* It *is* necessary to call this method when you stop
|
||||
@ -63,9 +63,9 @@ GIT_INLINE(int) git_tag_lookup_prefix(git_tag **tag, git_repository *repo, const
|
||||
* @param tag the tag to close
|
||||
*/
|
||||
|
||||
GIT_INLINE(void) git_tag_close(git_tag *tag)
|
||||
GIT_INLINE(void) git_tag_free(git_tag *tag)
|
||||
{
|
||||
git_object_close((git_object *) tag);
|
||||
git_object_free((git_object *) tag);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -1,40 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2009-2011 the libgit2 contributors
|
||||
*
|
||||
* This file is part of libgit2, distributed under the GNU GPL v2 with
|
||||
* a Linking Exception. For full terms see the included COPYING file.
|
||||
*/
|
||||
#ifndef INCLUDE_git_transport_h__
|
||||
#define INCLUDE_git_transport_h__
|
||||
|
||||
#include "common.h"
|
||||
#include "types.h"
|
||||
#include "net.h"
|
||||
|
||||
/**
|
||||
* @file git2/transport.h
|
||||
* @brief Git protocol transport abstraction
|
||||
* @defgroup git_transport Git protocol transport abstraction
|
||||
* @ingroup Git
|
||||
* @{
|
||||
*/
|
||||
GIT_BEGIN_DECL
|
||||
|
||||
/**
|
||||
* Get the appropriate transport for an URL.
|
||||
* @param tranport the transport for the url
|
||||
* @param url the url of the repo
|
||||
*/
|
||||
GIT_EXTERN(int) git_transport_new(git_transport **transport, const char *url);
|
||||
|
||||
/**
|
||||
* Return whether a string is a valid transport URL
|
||||
*
|
||||
* @param tranport the url to check
|
||||
* @param 1 if the url is valid, 0 otherwise
|
||||
*/
|
||||
GIT_EXTERN(int) git_transport_valid_url(const char *url);
|
||||
|
||||
/** @} */
|
||||
GIT_END_DECL
|
||||
#endif
|
||||
@ -54,7 +54,7 @@ GIT_INLINE(int) git_tree_lookup_prefix(git_tree **tree, git_repository *repo, co
|
||||
/**
|
||||
* Close an open tree
|
||||
*
|
||||
* This is a wrapper around git_object_close()
|
||||
* This is a wrapper around git_object_free()
|
||||
*
|
||||
* IMPORTANT:
|
||||
* It *is* necessary to call this method when you stop
|
||||
@ -63,9 +63,9 @@ GIT_INLINE(int) git_tree_lookup_prefix(git_tree **tree, git_repository *repo, co
|
||||
* @param tree the tree to close
|
||||
*/
|
||||
|
||||
GIT_INLINE(void) git_tree_close(git_tree *tree)
|
||||
GIT_INLINE(void) git_tree_free(git_tree *tree)
|
||||
{
|
||||
git_object_close((git_object *) tree);
|
||||
git_object_free((git_object *) tree);
|
||||
}
|
||||
|
||||
|
||||
@ -273,7 +273,7 @@ GIT_EXTERN(int) git_treebuilder_write(git_oid *oid, git_repository *repo, git_tr
|
||||
* relative path.
|
||||
*
|
||||
* The returned tree is owned by the repository and
|
||||
* should be closed with the `git_object_close` method.
|
||||
* should be closed with the `git_object_free` method.
|
||||
*
|
||||
* @param subtree Pointer where to store the subtree
|
||||
* @param root A previously loaded tree which will be the root of the relative path
|
||||
|
||||
@ -161,13 +161,7 @@ typedef enum {
|
||||
typedef struct git_refspec git_refspec;
|
||||
typedef struct git_remote git_remote;
|
||||
|
||||
/** A transport to use */
|
||||
typedef struct git_transport git_transport;
|
||||
|
||||
typedef int (*git_transport_cb)(git_transport **transport);
|
||||
|
||||
typedef struct git_remote_head git_remote_head;
|
||||
typedef struct git_headarray git_headarray;
|
||||
|
||||
/** @} */
|
||||
GIT_END_DECL
|
||||
|
||||
25
src/blob.c
25
src/blob.c
@ -26,7 +26,7 @@ size_t git_blob_rawsize(git_blob *blob)
|
||||
|
||||
void git_blob__free(git_blob *blob)
|
||||
{
|
||||
git_odb_object_close(blob->odb_object);
|
||||
git_odb_object_free(blob->odb_object);
|
||||
git__free(blob);
|
||||
}
|
||||
|
||||
@ -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");
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -60,4 +60,5 @@ extern void git___rethrow(const char *, ...) GIT_FORMAT_PRINTF(1, 2);
|
||||
|
||||
#include "util.h"
|
||||
|
||||
|
||||
#endif /* INCLUDE_common_h__ */
|
||||
|
||||
15
src/config.c
15
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;
|
||||
}
|
||||
|
||||
|
||||
@ -17,8 +17,8 @@
|
||||
#define GIT_CONFIG_FILE_MODE 0666
|
||||
|
||||
struct git_config {
|
||||
git_refcount rc;
|
||||
git_vector files;
|
||||
git_repository *repo;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@ -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);
|
||||
|
||||
110
src/fetch.c
110
src/fetch.c
@ -18,26 +18,46 @@
|
||||
#include "fetch.h"
|
||||
#include "netops.h"
|
||||
|
||||
struct filter_payload {
|
||||
git_remote *remote;
|
||||
const git_refspec *spec;
|
||||
git_odb *odb;
|
||||
int found_head;
|
||||
};
|
||||
|
||||
static int filter_ref__cb(git_remote_head *head, void *payload)
|
||||
{
|
||||
struct filter_payload *p = payload;
|
||||
int error;
|
||||
|
||||
if (!p->found_head && strcmp(head->name, GIT_HEAD_FILE) == 0) {
|
||||
p->found_head = 1;
|
||||
} else {
|
||||
/* If it doesn't match the refpec, we don't want it */
|
||||
error = git_refspec_src_match(p->spec, head->name);
|
||||
|
||||
if (error == GIT_ENOMATCH)
|
||||
return GIT_SUCCESS;
|
||||
|
||||
if (error < GIT_SUCCESS)
|
||||
return git__rethrow(error, "Error matching remote ref name");
|
||||
}
|
||||
|
||||
/* If we have the object, mark it so we don't ask for it */
|
||||
if (git_odb_exists(p->odb, &head->oid))
|
||||
head->local = 1;
|
||||
else
|
||||
p->remote->need_pack = 1;
|
||||
|
||||
return git_vector_insert(&p->remote->refs, head);
|
||||
}
|
||||
|
||||
static int filter_wants(git_remote *remote)
|
||||
{
|
||||
git_vector list;
|
||||
git_headarray refs;
|
||||
git_remote_head *head;
|
||||
git_transport *t = remote->transport;
|
||||
git_repository *repo = remote->repo;
|
||||
const git_refspec *spec;
|
||||
int error;
|
||||
unsigned int i = 0;
|
||||
struct filter_payload p;
|
||||
|
||||
error = git_vector_init(&list, 16, NULL);
|
||||
if (error < GIT_SUCCESS)
|
||||
return error;
|
||||
|
||||
error = t->ls(t, &refs);
|
||||
if (error < GIT_SUCCESS) {
|
||||
error = git__rethrow(error, "Failed to get remote ref list");
|
||||
goto cleanup;
|
||||
}
|
||||
git_vector_clear(&remote->refs);
|
||||
|
||||
/*
|
||||
* The fetch refspec can be NULL, and what this means is that the
|
||||
@ -45,56 +65,15 @@ static int filter_wants(git_remote *remote)
|
||||
* not interested in any particular branch but just the remote's
|
||||
* HEAD, which will be stored in FETCH_HEAD after the fetch.
|
||||
*/
|
||||
spec = git_remote_fetchspec(remote);
|
||||
p.spec = git_remote_fetchspec(remote);
|
||||
p.found_head = 0;
|
||||
p.remote = remote;
|
||||
|
||||
/*
|
||||
* We need to handle HEAD separately, as we always want it, but it
|
||||
* probably won't matcht he refspec.
|
||||
*/
|
||||
head = refs.heads[0];
|
||||
if (refs.len > 0 && !strcmp(head->name, GIT_HEAD_FILE)) {
|
||||
if (git_odb_exists(repo->db, &head->oid))
|
||||
head->local = 1;
|
||||
else
|
||||
remote->need_pack = 1;
|
||||
error = git_repository_odb__weakptr(&p.odb, remote->repo);
|
||||
if (error < GIT_SUCCESS)
|
||||
return error;
|
||||
|
||||
i = 1;
|
||||
error = git_vector_insert(&list, refs.heads[0]);
|
||||
if (error < GIT_SUCCESS)
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
for (; i < refs.len; ++i) {
|
||||
head = refs.heads[i];
|
||||
|
||||
/* If it doesn't match the refpec, we don't want it */
|
||||
error = git_refspec_src_match(spec, head->name);
|
||||
if (error == GIT_ENOMATCH)
|
||||
continue;
|
||||
if (error < GIT_SUCCESS) {
|
||||
error = git__rethrow(error, "Error matching remote ref name");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* If we have the object, mark it so we don't ask for it */
|
||||
if (git_odb_exists(repo->db, &head->oid))
|
||||
head->local = 1;
|
||||
else
|
||||
remote->need_pack = 1;
|
||||
|
||||
error = git_vector_insert(&list, head);
|
||||
if (error < GIT_SUCCESS)
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
remote->refs.len = list.length;
|
||||
remote->refs.heads = (git_remote_head **) list.contents;
|
||||
|
||||
return GIT_SUCCESS;
|
||||
|
||||
cleanup:
|
||||
git_vector_free(&list);
|
||||
return error;
|
||||
return remote->transport->ls(remote->transport, &filter_ref__cb, &p);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -112,8 +91,9 @@ int git_fetch_negotiate(git_remote *remote)
|
||||
return git__rethrow(error, "Failed to filter the reference list for wants");
|
||||
|
||||
/* Don't try to negotiate when we don't want anything */
|
||||
if (remote->refs.len == 0)
|
||||
if (remote->refs.length == 0)
|
||||
return GIT_SUCCESS;
|
||||
|
||||
if (!remote->need_pack)
|
||||
return GIT_SUCCESS;
|
||||
|
||||
|
||||
53
src/index.c
53
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);
|
||||
}
|
||||
git_index_clear(index);
|
||||
git_vector_free(&index->entries);
|
||||
git_vector_free(&index->unmerged);
|
||||
|
||||
/*
|
||||
* 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");
|
||||
|
||||
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->repository == NULL)
|
||||
return git__throw(GIT_EBAREINDEX, "Failed to initialize entry. Repository is bare");
|
||||
if (INDEX_OWNER(index) == NULL)
|
||||
return git__throw(GIT_EBAREINDEX,
|
||||
"Failed to initialize entry. Repository is bare");
|
||||
|
||||
git_path_join(full_path, index->repository->path_workdir, rel_path);
|
||||
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, 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));
|
||||
|
||||
@ -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;
|
||||
|
||||
31
src/object.c
31
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)
|
||||
{
|
||||
git_object_close(object);
|
||||
return git__throw(GIT_EINVALIDTYPE, "Failed to lookup object. The given type does not match the type on the ODB");
|
||||
if (type != GIT_OBJ_ANY && type != object->type) {
|
||||
git_object_free(object);
|
||||
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,14 +144,14 @@ 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)
|
||||
return git__rethrow(error, "Failed to lookup object");
|
||||
|
||||
if (type != GIT_OBJ_ANY && type != odb_obj->raw.type) {
|
||||
git_odb_object_close(odb_obj);
|
||||
git_odb_object_free(odb_obj);
|
||||
return git__throw(GIT_EINVALIDTYPE, "Failed to lookup object. The given type does not match the type on the ODB");
|
||||
}
|
||||
|
||||
@ -174,7 +185,7 @@ int git_object_lookup_prefix(git_object **object_out, git_repository *repo, cons
|
||||
break;
|
||||
}
|
||||
|
||||
git_odb_object_close(odb_obj);
|
||||
git_odb_object_free(odb_obj);
|
||||
|
||||
if (error < GIT_SUCCESS) {
|
||||
git_object__free(object);
|
||||
@ -218,7 +229,7 @@ void git_object__free(void *_obj)
|
||||
}
|
||||
}
|
||||
|
||||
void git_object_close(git_object *object)
|
||||
void git_object_free(git_object *object)
|
||||
{
|
||||
if (object == NULL)
|
||||
return;
|
||||
|
||||
24
src/odb.c
24
src/odb.c
@ -108,7 +108,7 @@ git_otype git_odb_object_type(git_odb_object *object)
|
||||
return object->raw.type;
|
||||
}
|
||||
|
||||
void git_odb_object_close(git_odb_object *object)
|
||||
void git_odb_object_free(git_odb_object *object)
|
||||
{
|
||||
git_cached_obj_decref((git_cached_obj *)object, &free_odb_object);
|
||||
}
|
||||
@ -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;
|
||||
@ -440,7 +446,7 @@ int git_odb_exists(git_odb *db, const git_oid *id)
|
||||
assert(db && id);
|
||||
|
||||
if ((object = git_cache_get(&db->cache, id)) != NULL) {
|
||||
git_odb_object_close(object);
|
||||
git_odb_object_free(object);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -466,7 +472,7 @@ int git_odb_read_header(size_t *len_p, git_otype *type_p, git_odb *db, const git
|
||||
if ((object = git_cache_get(&db->cache, id)) != NULL) {
|
||||
*len_p = object->raw.len;
|
||||
*type_p = object->raw.type;
|
||||
git_odb_object_close(object);
|
||||
git_odb_object_free(object);
|
||||
return GIT_SUCCESS;
|
||||
}
|
||||
|
||||
@ -491,7 +497,7 @@ int git_odb_read_header(size_t *len_p, git_otype *type_p, git_odb *db, const git
|
||||
|
||||
*len_p = object->raw.len;
|
||||
*type_p = object->raw.type;
|
||||
git_odb_object_close(object);
|
||||
git_odb_object_free(object);
|
||||
}
|
||||
|
||||
return GIT_SUCCESS;
|
||||
|
||||
@ -33,7 +33,7 @@ struct git_odb_object {
|
||||
|
||||
/* EXPORT */
|
||||
struct git_odb {
|
||||
void *_internal;
|
||||
git_refcount rc;
|
||||
git_vector backends;
|
||||
git_cache cache;
|
||||
};
|
||||
|
||||
24
src/pkt.c
24
src/pkt.c
@ -316,30 +316,30 @@ static int send_want_with_caps(git_remote_head *head, git_transport_caps *caps,
|
||||
* is overwrite the OID each time.
|
||||
*/
|
||||
|
||||
int git_pkt_buffer_wants(git_headarray *refs, git_transport_caps *caps, git_buf *buf)
|
||||
int git_pkt_buffer_wants(const git_vector *refs, git_transport_caps *caps, git_buf *buf)
|
||||
{
|
||||
unsigned int i = 0;
|
||||
int error;
|
||||
git_remote_head *head;
|
||||
|
||||
if (caps->common) {
|
||||
for (; i < refs->len; ++i) {
|
||||
head = refs->heads[i];
|
||||
for (; i < refs->length; ++i) {
|
||||
head = refs->contents[i];
|
||||
if (!head->local)
|
||||
break;
|
||||
}
|
||||
|
||||
error = buffer_want_with_caps(refs->heads[i], caps, buf);
|
||||
error = buffer_want_with_caps(refs->contents[i], caps, buf);
|
||||
if (error < GIT_SUCCESS)
|
||||
return git__rethrow(error, "Failed to buffer want with caps");
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
for (; i < refs->len; ++i) {
|
||||
for (; i < refs->length; ++i) {
|
||||
char oid[GIT_OID_HEXSZ];
|
||||
|
||||
head = refs->heads[i];
|
||||
head = refs->contents[i];
|
||||
if (head->local)
|
||||
continue;
|
||||
|
||||
@ -352,7 +352,7 @@ int git_pkt_buffer_wants(git_headarray *refs, git_transport_caps *caps, git_buf
|
||||
return git_pkt_buffer_flush(buf);
|
||||
}
|
||||
|
||||
int git_pkt_send_wants(git_headarray *refs, git_transport_caps *caps, int fd)
|
||||
int git_pkt_send_wants(const git_vector *refs, git_transport_caps *caps, int fd)
|
||||
{
|
||||
unsigned int i = 0;
|
||||
int error = GIT_SUCCESS;
|
||||
@ -365,15 +365,15 @@ int git_pkt_send_wants(git_headarray *refs, git_transport_caps *caps, int fd)
|
||||
|
||||
/* If there are common caps, find the first one */
|
||||
if (caps->common) {
|
||||
for (; i < refs->len; ++i) {
|
||||
head = refs->heads[i];
|
||||
for (; i < refs->length; ++i) {
|
||||
head = refs->contents[i];
|
||||
if (head->local)
|
||||
continue;
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
error = send_want_with_caps(refs->heads[i], caps, fd);
|
||||
error = send_want_with_caps(refs->contents[i], caps, fd);
|
||||
if (error < GIT_SUCCESS)
|
||||
return git__rethrow(error, "Failed to send want pkt with caps");
|
||||
/* Increase it here so it's correct whether we run this or not */
|
||||
@ -381,8 +381,8 @@ int git_pkt_send_wants(git_headarray *refs, git_transport_caps *caps, int fd)
|
||||
}
|
||||
|
||||
/* Continue from where we left off */
|
||||
for (; i < refs->len; ++i) {
|
||||
head = refs->heads[i];
|
||||
for (; i < refs->length; ++i) {
|
||||
head = refs->contents[i];
|
||||
if (head->local)
|
||||
continue;
|
||||
|
||||
|
||||
@ -68,8 +68,8 @@ int git_pkt_buffer_flush(git_buf *buf);
|
||||
int git_pkt_send_flush(int s);
|
||||
int git_pkt_buffer_done(git_buf *buf);
|
||||
int git_pkt_send_done(int s);
|
||||
int git_pkt_buffer_wants(git_headarray *refs, git_transport_caps *caps, git_buf *buf);
|
||||
int git_pkt_send_wants(git_headarray *refs, git_transport_caps *caps, int fd);
|
||||
int git_pkt_buffer_wants(const git_vector *refs, git_transport_caps *caps, git_buf *buf);
|
||||
int git_pkt_send_wants(const git_vector *refs, git_transport_caps *caps, int fd);
|
||||
int git_pkt_buffer_have(git_oid *oid, git_buf *buf);
|
||||
int git_pkt_send_have(git_oid *oid, int fd);
|
||||
void git_pkt_free(git_pkt *pkt);
|
||||
|
||||
21
src/refs.c
21
src/refs.c
@ -686,7 +686,7 @@ static int packed_find_peel(git_repository *repo, struct packref *ref)
|
||||
*/
|
||||
}
|
||||
|
||||
git_object_close(object);
|
||||
git_object_free(object);
|
||||
return GIT_SUCCESS;
|
||||
}
|
||||
|
||||
@ -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");
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
53
src/remote.c
53
src/remote.c
@ -70,16 +70,21 @@ int git_remote_new(git_remote **out, git_repository *repo, const char *url, cons
|
||||
memset(remote, 0x0, sizeof(git_remote));
|
||||
remote->repo = repo;
|
||||
|
||||
if (git_vector_init(&remote->refs, 32, NULL) < 0) {
|
||||
git_remote_free(remote);
|
||||
return GIT_ENOMEM;
|
||||
}
|
||||
|
||||
remote->url = git__strdup(url);
|
||||
if (remote->url == NULL) {
|
||||
git__free(remote);
|
||||
git_remote_free(remote);
|
||||
return GIT_ENOMEM;
|
||||
}
|
||||
|
||||
if (name != NULL) {
|
||||
remote->name = git__strdup(name);
|
||||
if (remote->name == NULL) {
|
||||
git__free(remote);
|
||||
git_remote_free(remote);
|
||||
return GIT_ENOMEM;
|
||||
}
|
||||
}
|
||||
@ -88,14 +93,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)
|
||||
@ -108,6 +118,11 @@ int git_remote_get(git_remote **out, git_config *cfg, const char *name)
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (git_vector_init(&remote->refs, 32, NULL) < 0) {
|
||||
error = GIT_ENOMEM;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* "fetch" is the longest var name we're interested in */
|
||||
buf_len = strlen("remote.") + strlen(".fetch") + strlen(name) + 1;
|
||||
buf = git__malloc(buf_len);
|
||||
@ -122,13 +137,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 +156,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 +168,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 +180,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);
|
||||
|
||||
@ -221,10 +237,14 @@ cleanup:
|
||||
return error;
|
||||
}
|
||||
|
||||
int git_remote_ls(git_remote *remote, git_headarray *refs)
|
||||
int git_remote_ls(git_remote *remote, git_headlist_cb list_cb, void *payload)
|
||||
{
|
||||
assert(remote && refs);
|
||||
return remote->transport->ls(remote->transport, refs);
|
||||
assert(remote);
|
||||
|
||||
if (!remote->transport)
|
||||
return git__throw(GIT_ERROR, "The remote is not connected");
|
||||
|
||||
return remote->transport->ls(remote->transport, list_cb, payload);
|
||||
}
|
||||
|
||||
int git_remote_download(char **filename, git_remote *remote)
|
||||
@ -244,7 +264,7 @@ int git_remote_update_tips(git_remote *remote)
|
||||
int error = GIT_SUCCESS;
|
||||
unsigned int i = 0;
|
||||
char refname[GIT_PATH_MAX];
|
||||
git_headarray *refs = &remote->refs;
|
||||
git_vector *refs = &remote->refs;
|
||||
git_remote_head *head;
|
||||
git_reference *ref;
|
||||
struct git_refspec *spec = &remote->fetch;
|
||||
@ -253,11 +273,11 @@ int git_remote_update_tips(git_remote *remote)
|
||||
|
||||
memset(refname, 0x0, sizeof(refname));
|
||||
|
||||
if (refs->len == 0)
|
||||
if (refs->length == 0)
|
||||
return GIT_SUCCESS;
|
||||
|
||||
/* HEAD is only allowed to be the first in the list */
|
||||
head = refs->heads[0];
|
||||
head = refs->contents[0];
|
||||
if (!strcmp(head->name, GIT_HEAD_FILE)) {
|
||||
error = git_reference_create_oid(&ref, remote->repo, GIT_FETCH_HEAD_FILE, &head->oid, 1);
|
||||
i = 1;
|
||||
@ -266,8 +286,8 @@ int git_remote_update_tips(git_remote *remote)
|
||||
return git__rethrow(error, "Failed to update FETCH_HEAD");
|
||||
}
|
||||
|
||||
for (; i < refs->len; ++i) {
|
||||
head = refs->heads[i];
|
||||
for (; i < refs->length; ++i) {
|
||||
head = refs->contents[i];
|
||||
|
||||
error = git_refspec_transform(refname, sizeof(refname), spec, head->name);
|
||||
if (error < GIT_SUCCESS)
|
||||
@ -313,6 +333,7 @@ void git_remote_free(git_remote *remote)
|
||||
git__free(remote->push.dst);
|
||||
git__free(remote->url);
|
||||
git__free(remote->name);
|
||||
git_vector_free(&remote->refs);
|
||||
git_remote_disconnect(remote);
|
||||
git__free(remote);
|
||||
}
|
||||
|
||||
@ -14,7 +14,7 @@
|
||||
struct git_remote {
|
||||
char *name;
|
||||
char *url;
|
||||
git_headarray refs;
|
||||
git_vector refs;
|
||||
struct git_refspec fetch;
|
||||
struct git_refspec push;
|
||||
git_transport *transport;
|
||||
|
||||
641
src/repository.c
641
src/repository.c
@ -24,118 +24,57 @@
|
||||
|
||||
#define GIT_BRANCH_MASTER "master"
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
static void drop_index(git_repository *repo)
|
||||
{
|
||||
if (repo->_index != NULL) {
|
||||
GIT_REFCOUNT_OWN(repo->_index, NULL);
|
||||
git_index_free(repo->_index);
|
||||
repo->_index = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void git_repository_free(git_repository *repo)
|
||||
{
|
||||
if (repo == NULL)
|
||||
return;
|
||||
|
||||
git_cache_free(&repo->objects);
|
||||
git_repository__refcache_free(&repo->references);
|
||||
|
||||
git__free(repo->path_repository);
|
||||
git__free(repo->workdir);
|
||||
|
||||
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 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");
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
return GIT_SUCCESS;
|
||||
}
|
||||
|
||||
static int check_repository_dirs(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;
|
||||
}
|
||||
|
||||
static int guess_repository_dirs(git_repository *repo, const char *repository_path)
|
||||
{
|
||||
char buffer[GIT_PATH_MAX];
|
||||
const char *path_work_tree = NULL;
|
||||
|
||||
/* 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);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
return assign_repository_dirs(repo, repository_path, NULL, NULL, path_work_tree);
|
||||
}
|
||||
|
||||
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,97 @@ 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;
|
||||
|
||||
error = git_repository_config__weakptr(&config, repo);
|
||||
if (error < GIT_SUCCESS)
|
||||
return error;
|
||||
|
||||
error = git_config_get_bool(config, "core.bare", &is_bare);
|
||||
if (error == GIT_SUCCESS)
|
||||
repo->is_bare = is_bare;
|
||||
|
||||
/* TODO: what else can we load/cache here? */
|
||||
|
||||
return GIT_SUCCESS;
|
||||
}
|
||||
|
||||
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)
|
||||
static int load_workdir(git_repository *repo)
|
||||
{
|
||||
if (!repo->is_bare) {
|
||||
char workdir_buf[GIT_PATH_MAX];
|
||||
|
||||
if (git_path_dirname_r(workdir_buf, sizeof(workdir_buf), repo->path_repository) < 0)
|
||||
return git__throw(GIT_EOSERR,
|
||||
"Failed to resolved working directory");
|
||||
|
||||
git_path_join(workdir_buf, workdir_buf, "");
|
||||
|
||||
repo->workdir = git__strdup(workdir_buf);
|
||||
if (repo->workdir == NULL)
|
||||
return GIT_ENOMEM;
|
||||
}
|
||||
|
||||
return GIT_SUCCESS;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
assert(repo_out);
|
||||
error = git_path_prettify_dir(path_buf, path, NULL);
|
||||
if (error < GIT_SUCCESS)
|
||||
return git__rethrow(error, "Failed to open repository");
|
||||
|
||||
if (object_database == NULL)
|
||||
return git__throw(GIT_EINVALIDARGS, "Failed to open repository. `object_database` can't be null");
|
||||
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,
|
||||
NULL,
|
||||
git_index_file,
|
||||
git_work_tree);
|
||||
|
||||
if (error < GIT_SUCCESS)
|
||||
goto cleanup;
|
||||
|
||||
error = check_repository_dirs(repo);
|
||||
if (error < GIT_SUCCESS)
|
||||
goto cleanup;
|
||||
|
||||
repo->db = object_database;
|
||||
|
||||
*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)
|
||||
{
|
||||
git_repository *repo;
|
||||
int error = GIT_SUCCESS;
|
||||
|
||||
assert(repo_out);
|
||||
|
||||
repo = repository_alloc();
|
||||
if (repo == NULL)
|
||||
repo->path_repository = git__strdup(path_buf);
|
||||
if (repo->path_repository == NULL) {
|
||||
git_repository_free(repo);
|
||||
return GIT_ENOMEM;
|
||||
}
|
||||
|
||||
error = assign_repository_dirs(repo,
|
||||
git_dir,
|
||||
git_object_directory,
|
||||
git_index_file,
|
||||
git_work_tree);
|
||||
error = load_config_data(repo);
|
||||
if (error < GIT_SUCCESS) {
|
||||
git_repository_free(repo);
|
||||
return error;
|
||||
}
|
||||
|
||||
if (error < GIT_SUCCESS)
|
||||
goto cleanup;
|
||||
|
||||
error = check_repository_dirs(repo);
|
||||
if (error < GIT_SUCCESS)
|
||||
goto cleanup;
|
||||
|
||||
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 +213,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];
|
||||
|
||||
error = git_config_find_global(global);
|
||||
global_path = error < GIT_SUCCESS ? NULL : global;
|
||||
const char *global_config_path = NULL;
|
||||
const char *system_config_path = NULL;
|
||||
|
||||
error = git_config_find_system(system);
|
||||
system_path = error < GIT_SUCCESS ? NULL : system;
|
||||
if (git_config_find_global(buf_global) == GIT_SUCCESS)
|
||||
global_config_path = buf_global;
|
||||
|
||||
return git_repository_config(out, repo, global_path, system_path);
|
||||
}
|
||||
if (git_config_find_system(buf_system) == GIT_SUCCESS)
|
||||
system_config_path = buf_system;
|
||||
|
||||
static int discover_repository_dirs(git_repository *repo, const char *path)
|
||||
{
|
||||
int error;
|
||||
error = load_config(&repo->_config, repo, global_config_path, system_config_path);
|
||||
if (error < GIT_SUCCESS)
|
||||
return error;
|
||||
|
||||
error = guess_repository_dirs(repo, path);
|
||||
if (error < GIT_SUCCESS)
|
||||
return error;
|
||||
|
||||
error = check_repository_dirs(repo);
|
||||
if (error < GIT_SUCCESS)
|
||||
return error;
|
||||
GIT_REFCOUNT_OWN(repo->_config, repo);
|
||||
}
|
||||
|
||||
*out = repo->_config;
|
||||
return GIT_SUCCESS;
|
||||
}
|
||||
|
||||
int git_repository_open(git_repository **repo_out, const char *path)
|
||||
int git_repository_config(git_config **out, git_repository *repo)
|
||||
{
|
||||
git_repository *repo;
|
||||
int error = GIT_SUCCESS;
|
||||
int error = git_repository_config__weakptr(out, repo);
|
||||
|
||||
assert(repo_out && path);
|
||||
if (error == GIT_SUCCESS) {
|
||||
GIT_REFCOUNT_INC(*out);
|
||||
}
|
||||
|
||||
repo = repository_alloc();
|
||||
if (repo == NULL)
|
||||
return GIT_ENOMEM;
|
||||
|
||||
error = discover_repository_dirs(repo, path);
|
||||
if (error < GIT_SUCCESS)
|
||||
goto cleanup;
|
||||
|
||||
error = init_odb(repo);
|
||||
if (error < GIT_SUCCESS)
|
||||
goto cleanup;
|
||||
|
||||
*repo_out = repo;
|
||||
return GIT_SUCCESS;
|
||||
|
||||
cleanup:
|
||||
git_repository_free(repo);
|
||||
return git__rethrow(error, "Failed to open repository");
|
||||
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_odb(git_odb **out, git_repository *repo)
|
||||
{
|
||||
int error = git_repository_odb__weakptr(out, repo);
|
||||
|
||||
if (error == GIT_SUCCESS) {
|
||||
GIT_REFCOUNT_INC(*out);
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
void git_repository_set_odb(git_repository *repo, git_odb *odb)
|
||||
{
|
||||
assert(repo && odb);
|
||||
|
||||
drop_odb(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;
|
||||
}
|
||||
|
||||
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 +483,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 +520,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 +561,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,42 +573,66 @@ 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;
|
||||
|
||||
error = git_reference_create_symbolic(&head_reference, repo, GIT_HEAD_FILE, GIT_REFS_HEADS_MASTER_FILE, 0);
|
||||
git_path_join(ref_path, git_dir, GIT_HEAD_FILE);
|
||||
|
||||
git_reference_free(head_reference);
|
||||
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_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;
|
||||
}
|
||||
|
||||
@ -674,31 +702,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);
|
||||
error = repo_init_createhead(repository_path);
|
||||
if (error < GIT_SUCCESS)
|
||||
goto cleanup;
|
||||
|
||||
error = repo_init_createhead(repo);
|
||||
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 +721,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 +738,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 +814,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;
|
||||
}
|
||||
|
||||
const char *git_repository_workdir(git_repository *repo)
|
||||
{
|
||||
assert(repo);
|
||||
|
||||
switch (id) {
|
||||
case GIT_REPO_PATH:
|
||||
return repo->path_repository;
|
||||
|
||||
case GIT_REPO_PATH_INDEX:
|
||||
return repo->path_index;
|
||||
|
||||
case GIT_REPO_PATH_ODB:
|
||||
return repo->path_odb;
|
||||
|
||||
case GIT_REPO_PATH_WORKDIR:
|
||||
return repo->path_workdir;
|
||||
|
||||
default:
|
||||
if (repo->is_bare)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return repo->workdir;
|
||||
}
|
||||
|
||||
int git_repository_set_workdir(git_repository *repo, const char *workdir)
|
||||
{
|
||||
assert(repo && workdir);
|
||||
|
||||
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)
|
||||
|
||||
@ -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
|
||||
|
||||
@ -34,6 +34,7 @@ typedef struct commit_list {
|
||||
|
||||
struct git_revwalk {
|
||||
git_repository *repo;
|
||||
git_odb *odb;
|
||||
|
||||
git_hashtable *commits;
|
||||
|
||||
@ -225,16 +226,16 @@ 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) {
|
||||
git_odb_object_close(obj);
|
||||
git_odb_object_free(obj);
|
||||
return git__throw(GIT_EOBJTYPE, "Failed to parse commit. Object is no commit object");
|
||||
}
|
||||
|
||||
error = commit_quick_parse(walk, commit, &obj->raw);
|
||||
git_odb_object_close(obj);
|
||||
git_odb_object_free(obj);
|
||||
return error == GIT_SUCCESS ? GIT_SUCCESS : git__rethrow(error, "Failed to parse 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.
|
||||
|
||||
72
src/status.c
72
src/status.c
@ -162,7 +162,7 @@ static int retrieve_head_tree(git_tree **tree_out, git_repository *repo)
|
||||
*tree_out = tree;
|
||||
|
||||
exit:
|
||||
git_commit_close(head_commit);
|
||||
git_commit_free(head_commit);
|
||||
return error;
|
||||
}
|
||||
|
||||
@ -214,7 +214,7 @@ static int process_folder(struct status_st *st, const git_tree_entry *tree_entry
|
||||
}
|
||||
|
||||
if (tree_entry_type == GIT_OBJ_TREE) {
|
||||
git_object_close(subtree);
|
||||
git_object_free(subtree);
|
||||
st->head_tree_relative_path_len -= 1 + tree_entry->filename_len;
|
||||
st->tree = pushed_tree;
|
||||
st->tree_position = pushed_tree_position;
|
||||
@ -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);
|
||||
@ -459,8 +477,7 @@ 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);
|
||||
git_tree_free(tree);
|
||||
return error;
|
||||
}
|
||||
|
||||
@ -495,7 +512,7 @@ static int recurse_tree_entry(git_tree *tree, struct status_entry *e, const char
|
||||
return git__throw(GIT_EOBJCORRUPTED, "Can't find tree object '%s'", tree_entry->filename);
|
||||
|
||||
error = recurse_tree_entry(subtree, e, dir_sep+1);
|
||||
git_tree_close(subtree);
|
||||
git_tree_free(subtree);
|
||||
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;
|
||||
}
|
||||
}
|
||||
@ -557,7 +585,7 @@ int git_status_file(unsigned int *status_flags, git_repository *repo, const char
|
||||
*status_flags = e->status_flags;
|
||||
|
||||
exit:
|
||||
git_tree_close(tree);
|
||||
git_tree_free(tree);
|
||||
git__free(e);
|
||||
return error;
|
||||
}
|
||||
|
||||
20
src/tag.c
20
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,18 +304,22 @@ 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)
|
||||
return git__throw(error, "The type for the given target is invalid");
|
||||
|
||||
git_odb_object_close(target_obj);
|
||||
git_odb_object_free(target_obj);
|
||||
|
||||
error = retrieve_tag_reference(&new_ref, ref_name, repo, tag.tag_name);
|
||||
|
||||
@ -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");
|
||||
}
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
*/
|
||||
#include "common.h"
|
||||
#include "git2/types.h"
|
||||
#include "git2/transport.h"
|
||||
#include "git2/remote.h"
|
||||
#include "git2/net.h"
|
||||
#include "transport.h"
|
||||
|
||||
@ -49,11 +49,6 @@ int git_transport_dummy(git_transport **GIT_UNUSED(transport))
|
||||
return git__throw(GIT_ENOTIMPLEMENTED, "This protocol isn't implemented. Sorry");
|
||||
}
|
||||
|
||||
int git_transport_valid_url(const char *url)
|
||||
{
|
||||
return transport_find_fn(url) != NULL;
|
||||
}
|
||||
|
||||
int git_transport_new(git_transport **out, const char *url)
|
||||
{
|
||||
git_transport_cb fn;
|
||||
@ -81,3 +76,10 @@ int git_transport_new(git_transport **out, const char *url)
|
||||
|
||||
return GIT_SUCCESS;
|
||||
}
|
||||
|
||||
/* from remote.h */
|
||||
int git_remote_valid_url(const char *url)
|
||||
{
|
||||
return transport_find_fn(url) != NULL;
|
||||
}
|
||||
|
||||
|
||||
@ -7,7 +7,6 @@
|
||||
#ifndef INCLUDE_transport_h__
|
||||
#define INCLUDE_transport_h__
|
||||
|
||||
#include "git2/transport.h"
|
||||
#include "git2/net.h"
|
||||
#include "vector.h"
|
||||
|
||||
@ -61,7 +60,7 @@ struct git_transport {
|
||||
/**
|
||||
* Give a list of references, useful for ls-remote
|
||||
*/
|
||||
int (*ls)(struct git_transport *transport, git_headarray *headarray);
|
||||
int (*ls)(struct git_transport *transport, git_headlist_cb list_cb, void *opaque);
|
||||
/**
|
||||
* Push the changes over
|
||||
*/
|
||||
@ -74,7 +73,7 @@ struct git_transport {
|
||||
* Negotiate the minimal amount of objects that need to be
|
||||
* retrieved
|
||||
*/
|
||||
int (*negotiate_fetch)(struct git_transport *transport, git_repository *repo, git_headarray *list);
|
||||
int (*negotiate_fetch)(struct git_transport *transport, git_repository *repo, const git_vector *wants);
|
||||
/**
|
||||
* Send a flush
|
||||
*/
|
||||
@ -97,9 +96,15 @@ struct git_transport {
|
||||
void (*free)(struct git_transport *transport);
|
||||
};
|
||||
|
||||
|
||||
int git_transport_new(struct git_transport **transport, const char *url);
|
||||
int git_transport_local(struct git_transport **transport);
|
||||
int git_transport_git(struct git_transport **transport);
|
||||
int git_transport_http(struct git_transport **transport);
|
||||
int git_transport_dummy(struct git_transport **transport);
|
||||
int git_transport_valid_url(const char *url);
|
||||
|
||||
typedef struct git_transport git_transport;
|
||||
typedef int (*git_transport_cb)(git_transport **transport);
|
||||
|
||||
#endif
|
||||
|
||||
@ -226,32 +226,30 @@ cleanup:
|
||||
return error;
|
||||
}
|
||||
|
||||
static int git_ls(git_transport *transport, git_headarray *array)
|
||||
static int git_ls(git_transport *transport, git_headlist_cb list_cb, void *opaque)
|
||||
{
|
||||
transport_git *t = (transport_git *) transport;
|
||||
git_vector *refs = &t->refs;
|
||||
int len = 0;
|
||||
unsigned int i;
|
||||
git_pkt *p = NULL;
|
||||
|
||||
array->heads = git__calloc(refs->length, sizeof(git_remote_head *));
|
||||
if (array->heads == NULL)
|
||||
return GIT_ENOMEM;
|
||||
git_vector_foreach(refs, i, p) {
|
||||
git_pkt_ref *pkt = NULL;
|
||||
|
||||
for (i = 0; i < refs->length; ++i) {
|
||||
git_pkt *p = git_vector_get(refs, i);
|
||||
if (p->type != GIT_PKT_REF)
|
||||
continue;
|
||||
|
||||
++len;
|
||||
array->heads[i] = &(((git_pkt_ref *) p)->head);
|
||||
pkt = (git_pkt_ref *)p;
|
||||
|
||||
if (list_cb(&pkt->head, opaque) < 0)
|
||||
return git__throw(GIT_ERROR,
|
||||
"The user callback returned an error code");
|
||||
}
|
||||
array->len = len;
|
||||
t->heads = array->heads;
|
||||
|
||||
return GIT_SUCCESS;
|
||||
}
|
||||
|
||||
static int git_negotiate_fetch(git_transport *transport, git_repository *repo, git_headarray *wants)
|
||||
static int git_negotiate_fetch(git_transport *transport, git_repository *repo, const git_vector *wants)
|
||||
{
|
||||
transport_git *t = (transport_git *) transport;
|
||||
git_revwalk *walk;
|
||||
@ -290,6 +288,7 @@ static int git_negotiate_fetch(git_transport *transport, git_repository *repo, g
|
||||
|
||||
if (git_reference_type(ref) == GIT_REF_SYMBOLIC)
|
||||
continue;
|
||||
|
||||
error = git_revwalk_push(walk, git_reference_oid(ref));
|
||||
if (error < GIT_ERROR) {
|
||||
error = git__rethrow(error, "Failed to push %s", refs.strings[i]);
|
||||
|
||||
@ -301,29 +301,22 @@ cleanup:
|
||||
return error;
|
||||
}
|
||||
|
||||
static int http_ls(git_transport *transport, git_headarray *array)
|
||||
static int http_ls(git_transport *transport, git_headlist_cb list_cb, void *opaque)
|
||||
{
|
||||
transport_http *t = (transport_http *) transport;
|
||||
git_vector *refs = &t->refs;
|
||||
unsigned int i;
|
||||
int len = 0;
|
||||
git_pkt_ref *p;
|
||||
|
||||
array->heads = git__calloc(refs->length, sizeof(git_remote_head*));
|
||||
if (array->heads == NULL)
|
||||
return GIT_ENOMEM;
|
||||
|
||||
git_vector_foreach(refs, i, p) {
|
||||
if (p->type != GIT_PKT_REF)
|
||||
continue;
|
||||
|
||||
array->heads[len] = &p->head;
|
||||
len++;
|
||||
if (list_cb(&p->head, opaque) < 0)
|
||||
return git__throw(GIT_ERROR,
|
||||
"The user callback returned an error code");
|
||||
}
|
||||
|
||||
array->len = len;
|
||||
t->heads = array->heads;
|
||||
|
||||
return GIT_SUCCESS;
|
||||
}
|
||||
|
||||
@ -470,7 +463,7 @@ cleanup:
|
||||
return error;
|
||||
}
|
||||
|
||||
static int http_negotiate_fetch(git_transport *transport, git_repository *repo, git_headarray *wants)
|
||||
static int http_negotiate_fetch(git_transport *transport, git_repository *repo, const git_vector *wants)
|
||||
{
|
||||
transport_http *t = (transport_http *) transport;
|
||||
int error;
|
||||
|
||||
@ -6,7 +6,6 @@
|
||||
*/
|
||||
#include "common.h"
|
||||
#include "git2/types.h"
|
||||
#include "git2/transport.h"
|
||||
#include "git2/net.h"
|
||||
#include "git2/repository.h"
|
||||
#include "git2/object.h"
|
||||
@ -18,9 +17,137 @@
|
||||
typedef struct {
|
||||
git_transport parent;
|
||||
git_repository *repo;
|
||||
git_vector *refs;
|
||||
git_vector refs;
|
||||
} transport_local;
|
||||
|
||||
static int add_ref(transport_local *t, const char *name)
|
||||
{
|
||||
const char peeled[] = "^{}";
|
||||
git_remote_head *head;
|
||||
git_reference *ref, *resolved_ref;
|
||||
git_object *obj = NULL;
|
||||
int error = GIT_SUCCESS, peel_len, ret;
|
||||
|
||||
head = git__malloc(sizeof(git_remote_head));
|
||||
if (head == NULL)
|
||||
return GIT_ENOMEM;
|
||||
|
||||
head->name = git__strdup(name);
|
||||
if (head->name == NULL) {
|
||||
error = GIT_ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
error = git_reference_lookup(&ref, t->repo, name);
|
||||
if (error < GIT_SUCCESS)
|
||||
goto out;
|
||||
|
||||
error = git_reference_resolve(&resolved_ref, ref);
|
||||
if (error < GIT_SUCCESS)
|
||||
goto out;
|
||||
|
||||
git_oid_cpy(&head->oid, git_reference_oid(ref));
|
||||
|
||||
error = git_vector_insert(&t->refs, head);
|
||||
if (error < GIT_SUCCESS)
|
||||
goto out;
|
||||
|
||||
head = NULL;
|
||||
|
||||
/* If it's not a tag, we don't need to try to peel it */
|
||||
if (git__prefixcmp(name, GIT_REFS_TAGS_DIR))
|
||||
goto out;
|
||||
|
||||
error = git_object_lookup(&obj, t->repo, &head->oid, GIT_OBJ_ANY);
|
||||
if (error < GIT_SUCCESS) {
|
||||
git__rethrow(error, "Failed to lookup object");
|
||||
}
|
||||
|
||||
/* If it's not an annotated tag, just get out */
|
||||
if (git_object_type(obj) != GIT_OBJ_TAG)
|
||||
goto out;
|
||||
|
||||
/* And if it's a tag, peel it, and add it to the list */
|
||||
head = git__malloc(sizeof(git_remote_head));
|
||||
peel_len = strlen(name) + strlen(peeled);
|
||||
head->name = git__malloc(peel_len + 1);
|
||||
ret = p_snprintf(head->name, peel_len + 1, "%s%s", name, peeled);
|
||||
|
||||
assert(ret < peel_len + 1);
|
||||
|
||||
git_oid_cpy(&head->oid, git_tag_target_oid((git_tag *) obj));
|
||||
|
||||
error = git_vector_insert(&t->refs, head);
|
||||
if (error < GIT_SUCCESS)
|
||||
goto out;
|
||||
|
||||
out:
|
||||
git_reference_free(ref);
|
||||
git_reference_free(resolved_ref);
|
||||
|
||||
git_object_free(obj);
|
||||
if (head && error < GIT_SUCCESS) {
|
||||
git__free(head->name);
|
||||
git__free(head);
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
static int store_refs(transport_local *t)
|
||||
{
|
||||
int error;
|
||||
unsigned int i;
|
||||
git_strarray ref_names = {0};
|
||||
|
||||
assert(t);
|
||||
|
||||
error = git_vector_init(&t->refs, ref_names.count, NULL);
|
||||
if (error < GIT_SUCCESS)
|
||||
return error;
|
||||
|
||||
error = git_reference_listall(&ref_names, t->repo, GIT_REF_LISTALL);
|
||||
if (error < GIT_SUCCESS)
|
||||
return git__rethrow(error, "Failed to list remote heads");
|
||||
|
||||
/* Sort the references first */
|
||||
git__tsort((void **)ref_names.strings, ref_names.count, &git__strcmp_cb);
|
||||
|
||||
/* Add HEAD */
|
||||
error = add_ref(t, GIT_HEAD_FILE);
|
||||
if (error < GIT_SUCCESS)
|
||||
goto cleanup;
|
||||
|
||||
for (i = 0; i < ref_names.count; ++i) {
|
||||
error = add_ref(t, ref_names.strings[i]);
|
||||
if (error < GIT_SUCCESS)
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
cleanup:
|
||||
git_strarray_free(&ref_names);
|
||||
return error;
|
||||
}
|
||||
|
||||
static int local_ls(git_transport *transport, git_headlist_cb list_cb, void *payload)
|
||||
{
|
||||
transport_local *t = (transport_local *) transport;
|
||||
git_vector *refs = &t->refs;
|
||||
unsigned int i;
|
||||
git_remote_head *h;
|
||||
|
||||
assert(transport && transport->connected);
|
||||
|
||||
git_vector_foreach(refs, i, h) {
|
||||
if (list_cb(h, payload) < 0)
|
||||
return git__throw(GIT_ERROR,
|
||||
"The user callback returned an error code");
|
||||
}
|
||||
|
||||
return GIT_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Try to open the url as a git directory. The direction doesn't
|
||||
* matter in this case because we're calulating the heads ourselves.
|
||||
@ -44,141 +171,23 @@ static int local_connect(git_transport *transport, int GIT_UNUSED(direction))
|
||||
if (error < GIT_SUCCESS)
|
||||
return git__rethrow(error, "Failed to open remote");
|
||||
|
||||
error = store_refs(t);
|
||||
if (error < GIT_SUCCESS)
|
||||
return git__rethrow(error, "Failed to retrieve references");
|
||||
|
||||
t->repo = repo;
|
||||
t->parent.connected = 1;
|
||||
|
||||
return GIT_SUCCESS;
|
||||
}
|
||||
|
||||
static int add_ref(const char *name, git_repository *repo, git_vector *vec)
|
||||
{
|
||||
const char peeled[] = "^{}";
|
||||
git_remote_head *head;
|
||||
git_reference *ref, *resolved_ref;
|
||||
git_object *obj = NULL;
|
||||
int error = GIT_SUCCESS, peel_len, ret;
|
||||
|
||||
head = git__malloc(sizeof(git_remote_head));
|
||||
if (head == NULL)
|
||||
return GIT_ENOMEM;
|
||||
|
||||
head->name = git__strdup(name);
|
||||
if (head->name == NULL) {
|
||||
error = GIT_ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
error = git_reference_lookup(&ref, repo, name);
|
||||
if (error < GIT_SUCCESS)
|
||||
goto out;
|
||||
|
||||
error = git_reference_resolve(&resolved_ref, ref);
|
||||
if (error < GIT_SUCCESS)
|
||||
goto out;
|
||||
|
||||
git_oid_cpy(&head->oid, git_reference_oid(ref));
|
||||
|
||||
error = git_vector_insert(vec, head);
|
||||
if (error < GIT_SUCCESS)
|
||||
goto out;
|
||||
|
||||
/* If it's not a tag, we don't need to try to peel it */
|
||||
if (git__prefixcmp(name, GIT_REFS_TAGS_DIR))
|
||||
goto out;
|
||||
|
||||
error = git_object_lookup(&obj, repo, &head->oid, GIT_OBJ_ANY);
|
||||
if (error < GIT_SUCCESS) {
|
||||
git__rethrow(error, "Failed to lookup object");
|
||||
}
|
||||
|
||||
/* If it's not an annotated tag, just get out */
|
||||
if (git_object_type(obj) != GIT_OBJ_TAG)
|
||||
goto out;
|
||||
|
||||
/* And if it's a tag, peel it, and add it to the list */
|
||||
head = git__malloc(sizeof(git_remote_head));
|
||||
peel_len = strlen(name) + strlen(peeled);
|
||||
head->name = git__malloc(peel_len + 1);
|
||||
ret = p_snprintf(head->name, peel_len + 1, "%s%s", name, peeled);
|
||||
if (ret >= peel_len + 1) {
|
||||
error = git__throw(GIT_ERROR, "The string is magically to long");
|
||||
}
|
||||
|
||||
git_oid_cpy(&head->oid, git_tag_target_oid((git_tag *) obj));
|
||||
|
||||
error = git_vector_insert(vec, head);
|
||||
if (error < GIT_SUCCESS)
|
||||
goto out;
|
||||
|
||||
out:
|
||||
git_reference_free(ref);
|
||||
git_reference_free(resolved_ref);
|
||||
|
||||
git_object_close(obj);
|
||||
if (error < GIT_SUCCESS) {
|
||||
git__free(head->name);
|
||||
git__free(head);
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
static int local_ls(git_transport *transport, git_headarray *array)
|
||||
{
|
||||
int error;
|
||||
unsigned int i;
|
||||
git_repository *repo;
|
||||
git_vector *vec;
|
||||
git_strarray refs;
|
||||
transport_local *t = (transport_local *) transport;
|
||||
|
||||
assert(transport && transport->connected);
|
||||
|
||||
repo = t->repo;
|
||||
|
||||
error = git_reference_listall(&refs, repo, GIT_REF_LISTALL);
|
||||
if (error < GIT_SUCCESS)
|
||||
return git__rethrow(error, "Failed to list remote heads");
|
||||
|
||||
vec = git__malloc(sizeof(git_vector));
|
||||
if (vec == NULL) {
|
||||
error = GIT_ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
error = git_vector_init(vec, refs.count, NULL);
|
||||
if (error < GIT_SUCCESS)
|
||||
return error;
|
||||
|
||||
/* Sort the references first */
|
||||
git__tsort((void **)refs.strings, refs.count, &git__strcmp_cb);
|
||||
|
||||
/* Add HEAD */
|
||||
error = add_ref(GIT_HEAD_FILE, repo, vec);
|
||||
if (error < GIT_SUCCESS)
|
||||
goto out;
|
||||
|
||||
for (i = 0; i < refs.count; ++i) {
|
||||
error = add_ref(refs.strings[i], repo, vec);
|
||||
if (error < GIT_SUCCESS)
|
||||
goto out;
|
||||
}
|
||||
|
||||
array->len = vec->length;
|
||||
array->heads = (git_remote_head **)vec->contents;
|
||||
|
||||
t->refs = vec;
|
||||
|
||||
out:
|
||||
|
||||
git_strarray_free(&refs);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
static int local_close(git_transport *GIT_UNUSED(transport))
|
||||
{
|
||||
/* Nothing to do */
|
||||
GIT_UNUSED_ARG(transport);
|
||||
transport_local *t = (transport_local *)transport;
|
||||
|
||||
git_repository_free(t->repo);
|
||||
t->repo = NULL;
|
||||
|
||||
return GIT_SUCCESS;
|
||||
}
|
||||
|
||||
@ -186,21 +195,17 @@ static void local_free(git_transport *transport)
|
||||
{
|
||||
unsigned int i;
|
||||
transport_local *t = (transport_local *) transport;
|
||||
git_vector *vec = t->refs;
|
||||
git_vector *vec = &t->refs;
|
||||
git_remote_head *h;
|
||||
|
||||
assert(transport);
|
||||
|
||||
if (t->refs != NULL) {
|
||||
git_vector_foreach (vec, i, h) {
|
||||
git__free(h->name);
|
||||
git__free(h);
|
||||
}
|
||||
git_vector_free(vec);
|
||||
git__free(vec);
|
||||
git_vector_foreach (vec, i, h) {
|
||||
git__free(h->name);
|
||||
git__free(h);
|
||||
}
|
||||
git_vector_free(vec);
|
||||
|
||||
git_repository_free(t->repo);
|
||||
git__free(t->parent.url);
|
||||
git__free(t);
|
||||
}
|
||||
|
||||
36
src/tree.c
36
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");
|
||||
@ -662,7 +680,7 @@ static int tree_frompath(
|
||||
slash_pos - treeentry_path + 1
|
||||
);
|
||||
|
||||
git_tree_close(subtree);
|
||||
git_tree_free(subtree);
|
||||
return error;
|
||||
}
|
||||
|
||||
@ -713,7 +731,7 @@ static int tree_walk_post(
|
||||
payload
|
||||
);
|
||||
|
||||
git_tree_close(subtree);
|
||||
git_tree_free(subtree);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
43
src/util.h
43
src/util.h
@ -104,29 +104,34 @@ extern void git__strtolower(char *str);
|
||||
|
||||
extern int git__fnmatch(const char *pattern, const char *name, int flags);
|
||||
|
||||
/*
|
||||
* Realloc the buffer pointed at by variable 'x' so that it can hold
|
||||
* at least 'nr' entries; the number of entries currently allocated
|
||||
* is 'alloc', using the standard growing factor alloc_nr() macro.
|
||||
*
|
||||
* DO NOT USE any expression with side-effect for 'x' or 'alloc'.
|
||||
*/
|
||||
#define alloc_nr(x) (((x)+16)*3/2)
|
||||
#define ALLOC_GROW(x, nr, alloc) \
|
||||
do { \
|
||||
if ((nr) > alloc) { \
|
||||
if (alloc_nr(alloc) < (nr)) \
|
||||
alloc = (nr); \
|
||||
else \
|
||||
alloc = alloc_nr(alloc); \
|
||||
x = xrealloc((x), alloc * sizeof(*(x))); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
extern void git__tsort(void **dst, size_t size, int (*cmp)(const void *, const void *));
|
||||
extern void **git__bsearch(const void *key, void **base, size_t nmemb,
|
||||
int (*compar)(const void *, const void *));
|
||||
|
||||
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__ */
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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}
|
||||
};
|
||||
@ -230,18 +280,36 @@ static const struct clay_suite _clay_suites[] = {
|
||||
{NULL, NULL},
|
||||
{NULL, NULL},
|
||||
_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",
|
||||
@ -356,6 +424,42 @@ static const struct clay_suite _clay_suites[] = {
|
||||
{"initialize", &test_object_tree_frompath__initialize},
|
||||
{"cleanup", &test_object_tree_frompath__cleanup},
|
||||
_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",
|
||||
@ -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
|
||||
|
||||
37
tests-clay/config/add.c
Normal file
37
tests-clay/config/add.c
Normal file
@ -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);
|
||||
}
|
||||
209
tests-clay/config/read.c
Normal file
209
tests-clay/config/read.c
Normal file
@ -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
|
||||
@ -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));
|
||||
|
||||
|
||||
77
tests-clay/config/write.c
Normal file
77
tests-clay/config/write.c
Normal file
@ -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);
|
||||
}
|
||||
@ -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"));
|
||||
}
|
||||
|
||||
@ -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));
|
||||
@ -21,8 +19,9 @@ void test_object_tree_frompath__initialize(void)
|
||||
|
||||
void test_object_tree_frompath__cleanup(void)
|
||||
{
|
||||
git_tree_close(tree);
|
||||
git_tree_free(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)
|
||||
@ -38,7 +37,7 @@ static void assert_tree_from_path(git_tree *root, const char *path, git_error ex
|
||||
|
||||
cl_assert(git_oid_streq(git_object_id((const git_object *)containing_tree), expected_raw_oid) == GIT_SUCCESS);
|
||||
|
||||
git_tree_close(containing_tree);
|
||||
git_tree_free(containing_tree);
|
||||
}
|
||||
|
||||
void test_object_tree_frompath__retrieve_tree_from_path_to_treeentry(void)
|
||||
|
||||
84
tests-clay/odb/loose.c
Normal file
84
tests-clay/odb/loose.c
Normal file
@ -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_free(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);
|
||||
}
|
||||
@ -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),
|
||||
};
|
||||
|
||||
@ -149,4 +149,3 @@ static const char *loose_objects[] = {
|
||||
"a4a7dce85cf63874e984719f4fdd239f5145052f",
|
||||
"4a202b346bb0fb0db7eff3cffeb3c70babbd2045"
|
||||
};
|
||||
|
||||
78
tests-clay/odb/packed.c
Normal file
78
tests-clay/odb/packed.c
Normal file
@ -0,0 +1,78 @@
|
||||
#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_free(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_free(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_free(obj);
|
||||
}
|
||||
}
|
||||
|
||||
71
tests-clay/odb/sorting.c
Normal file
71
tests-clay/odb/sorting.c
Normal file
@ -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);
|
||||
}
|
||||
68
tests-clay/repo/getters.c
Normal file
68
tests-clay/repo/getters.c
Normal file
@ -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);
|
||||
}
|
||||
104
tests-clay/repo/init.c
Normal file
104
tests-clay/repo/init.c
Normal file
@ -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
|
||||
54
tests-clay/repo/open.c
Normal file
54
tests-clay/repo/open.c
Normal file
@ -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
|
||||
0
tests/resources/bad_tag.git/refs/dummy-marker.txt
Normal file
0
tests/resources/bad_tag.git/refs/dummy-marker.txt
Normal file
@ -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
|
||||
@ -113,8 +113,8 @@ BEGIN_TEST(write0, "write loose commit object")
|
||||
must_pass(git_odb_read(&obj, db, &id1));
|
||||
must_pass(cmp_objects(&obj->raw, &commit_obj));
|
||||
|
||||
git_odb_object_close(obj);
|
||||
git_odb_close(db);
|
||||
git_odb_object_free(obj);
|
||||
git_odb_free(db);
|
||||
must_pass(remove_object_files(&commit));
|
||||
END_TEST
|
||||
|
||||
@ -134,8 +134,8 @@ BEGIN_TEST(write1, "write loose tree object")
|
||||
must_pass(git_odb_read(&obj, db, &id1));
|
||||
must_pass(cmp_objects(&obj->raw, &tree_obj));
|
||||
|
||||
git_odb_object_close(obj);
|
||||
git_odb_close(db);
|
||||
git_odb_object_free(obj);
|
||||
git_odb_free(db);
|
||||
must_pass(remove_object_files(&tree));
|
||||
END_TEST
|
||||
|
||||
@ -155,8 +155,8 @@ BEGIN_TEST(write2, "write loose tag object")
|
||||
must_pass(git_odb_read(&obj, db, &id1));
|
||||
must_pass(cmp_objects(&obj->raw, &tag_obj));
|
||||
|
||||
git_odb_object_close(obj);
|
||||
git_odb_close(db);
|
||||
git_odb_object_free(obj);
|
||||
git_odb_free(db);
|
||||
must_pass(remove_object_files(&tag));
|
||||
END_TEST
|
||||
|
||||
@ -176,8 +176,8 @@ BEGIN_TEST(write3, "write zero-length object")
|
||||
must_pass(git_odb_read(&obj, db, &id1));
|
||||
must_pass(cmp_objects(&obj->raw, &zero_obj));
|
||||
|
||||
git_odb_object_close(obj);
|
||||
git_odb_close(db);
|
||||
git_odb_object_free(obj);
|
||||
git_odb_free(db);
|
||||
must_pass(remove_object_files(&zero));
|
||||
END_TEST
|
||||
|
||||
@ -197,8 +197,8 @@ BEGIN_TEST(write4, "write one-byte long object")
|
||||
must_pass(git_odb_read(&obj, db, &id1));
|
||||
must_pass(cmp_objects(&obj->raw, &one_obj));
|
||||
|
||||
git_odb_object_close(obj);
|
||||
git_odb_close(db);
|
||||
git_odb_object_free(obj);
|
||||
git_odb_free(db);
|
||||
must_pass(remove_object_files(&one));
|
||||
END_TEST
|
||||
|
||||
@ -218,8 +218,8 @@ BEGIN_TEST(write5, "write two-byte long object")
|
||||
must_pass(git_odb_read(&obj, db, &id1));
|
||||
must_pass(cmp_objects(&obj->raw, &two_obj));
|
||||
|
||||
git_odb_object_close(obj);
|
||||
git_odb_close(db);
|
||||
git_odb_object_free(obj);
|
||||
git_odb_free(db);
|
||||
must_pass(remove_object_files(&two));
|
||||
END_TEST
|
||||
|
||||
@ -239,8 +239,8 @@ BEGIN_TEST(write6, "write an object which is several bytes long")
|
||||
must_pass(git_odb_read(&obj, db, &id1));
|
||||
must_pass(cmp_objects(&obj->raw, &some_obj));
|
||||
|
||||
git_odb_object_close(obj);
|
||||
git_odb_close(db);
|
||||
git_odb_object_free(obj);
|
||||
git_odb_free(db);
|
||||
must_pass(remove_object_files(&some));
|
||||
END_TEST
|
||||
|
||||
|
||||
@ -609,18 +609,18 @@ BEGIN_TEST(details0, "query the details on a parsed commit")
|
||||
must_be_true(parents <= 2);
|
||||
for (p = 0;p < parents;p++) {
|
||||
if (old_parent != NULL)
|
||||
git_commit_close(old_parent);
|
||||
git_commit_free(old_parent);
|
||||
|
||||
old_parent = parent;
|
||||
must_pass(git_commit_parent(&parent, commit, p));
|
||||
must_be_true(parent != NULL);
|
||||
must_be_true(git_commit_author(parent) != NULL); // is it really a commit?
|
||||
}
|
||||
git_commit_close(old_parent);
|
||||
git_commit_close(parent);
|
||||
git_commit_free(old_parent);
|
||||
git_commit_free(parent);
|
||||
|
||||
must_fail(git_commit_parent(&parent, commit, parents));
|
||||
git_commit_close(commit);
|
||||
git_commit_free(commit);
|
||||
}
|
||||
|
||||
git_repository_free(repo);
|
||||
@ -665,8 +665,8 @@ BEGIN_TEST(write0, "write a new commit object from memory to disk")
|
||||
tree,
|
||||
1, parent));
|
||||
|
||||
git_object_close((git_object *)parent);
|
||||
git_object_close((git_object *)tree);
|
||||
git_object_free((git_object *)parent);
|
||||
git_object_free((git_object *)tree);
|
||||
|
||||
git_signature_free(committer);
|
||||
git_signature_free(author);
|
||||
@ -696,7 +696,7 @@ BEGIN_TEST(write0, "write a new commit object from memory to disk")
|
||||
|
||||
must_pass(remove_loose_object(REPOSITORY_FOLDER, (git_object *)commit));
|
||||
|
||||
git_commit_close(commit);
|
||||
git_commit_free(commit);
|
||||
git_repository_free(repo);
|
||||
END_TEST
|
||||
|
||||
@ -742,7 +742,7 @@ BEGIN_TEST(root0, "create a root commit")
|
||||
tree,
|
||||
0));
|
||||
|
||||
git_object_close((git_object *)tree);
|
||||
git_object_free((git_object *)tree);
|
||||
git_signature_free(committer);
|
||||
git_signature_free(author);
|
||||
|
||||
@ -764,7 +764,7 @@ BEGIN_TEST(root0, "create a root commit")
|
||||
must_pass(git_reference_delete(branch));
|
||||
must_pass(remove_loose_object(REPOSITORY_FOLDER, (git_object *)commit));
|
||||
git__free(head_old);
|
||||
git_commit_close(commit);
|
||||
git_commit_free(commit);
|
||||
git_repository_free(repo);
|
||||
|
||||
git_reference_free(head);
|
||||
|
||||
@ -60,9 +60,9 @@ BEGIN_TEST(read0, "read and parse a tag from the repository")
|
||||
|
||||
must_be_true(git_oid_cmp(&id_commit, git_commit_id(commit)) == 0);
|
||||
|
||||
git_tag_close(tag1);
|
||||
git_tag_close(tag2);
|
||||
git_commit_close(commit);
|
||||
git_tag_free(tag1);
|
||||
git_tag_free(tag2);
|
||||
git_commit_free(commit);
|
||||
git_repository_free(repo);
|
||||
END_TEST
|
||||
|
||||
@ -133,8 +133,8 @@ BEGIN_TEST(read3, "read and parse a tag without a tagger field")
|
||||
|
||||
must_be_true(git_oid_cmp(&id_commit, git_commit_id(commit)) == 0);
|
||||
|
||||
git_tag_close(bad_tag);
|
||||
git_commit_close(commit);
|
||||
git_tag_free(bad_tag);
|
||||
git_commit_free(commit);
|
||||
|
||||
git_repository_free(repo);
|
||||
END_TEST
|
||||
@ -170,7 +170,7 @@ BEGIN_TEST(write0, "write a tag to the repository and read it again")
|
||||
TAGGER_MESSAGE,
|
||||
0));
|
||||
|
||||
git_object_close(target);
|
||||
git_object_free(target);
|
||||
git_signature_free(tagger);
|
||||
|
||||
must_pass(git_tag_lookup(&tag, repo, &tag_id));
|
||||
@ -195,7 +195,7 @@ BEGIN_TEST(write0, "write a tag to the repository and read it again")
|
||||
|
||||
must_pass(remove_loose_object(REPOSITORY_FOLDER, (git_object *)tag));
|
||||
|
||||
git_tag_close(tag);
|
||||
git_tag_free(tag);
|
||||
git_repository_free(repo);
|
||||
END_TEST
|
||||
|
||||
@ -222,7 +222,7 @@ BEGIN_TEST(write2, "Attempt to write a tag bearing the same name than an already
|
||||
TAGGER_MESSAGE,
|
||||
0));
|
||||
|
||||
git_object_close(target);
|
||||
git_object_free(target);
|
||||
git_signature_free(tagger);
|
||||
|
||||
git_repository_free(repo);
|
||||
@ -256,7 +256,7 @@ BEGIN_TEST(write3, "Replace an already existing tag")
|
||||
TAGGER_MESSAGE,
|
||||
1));
|
||||
|
||||
git_object_close(target);
|
||||
git_object_free(target);
|
||||
git_signature_free(tagger);
|
||||
|
||||
must_pass(git_reference_lookup(&ref_tag, repo, "refs/tags/e90810b"));
|
||||
@ -286,7 +286,7 @@ BEGIN_TEST(write4, "write a lightweight tag to the repository and read it again"
|
||||
target,
|
||||
0));
|
||||
|
||||
git_object_close(target);
|
||||
git_object_free(target);
|
||||
|
||||
must_be_true(git_oid_cmp(&object_id, &target_id) == 0);
|
||||
|
||||
@ -320,7 +320,7 @@ BEGIN_TEST(write5, "Attempt to write a lightweight tag bearing the same name tha
|
||||
git_oid_fromstr(&existing_object_id, tag2_id);
|
||||
must_be_true(git_oid_cmp(&object_id, &existing_object_id) == 0);
|
||||
|
||||
git_object_close(target);
|
||||
git_object_free(target);
|
||||
|
||||
git_repository_free(repo);
|
||||
END_TEST
|
||||
|
||||
@ -53,13 +53,13 @@ static int print_tree(git_repository *repo, const git_oid *tree_oid, int depth)
|
||||
|
||||
if (entry->attr == S_IFDIR) {
|
||||
if (print_tree(repo, &entry->oid, depth + 1) < GIT_SUCCESS) {
|
||||
git_tree_close(tree);
|
||||
git_tree_free(tree);
|
||||
return GIT_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
git_tree_close(tree);
|
||||
git_tree_free(tree);
|
||||
return GIT_SUCCESS;
|
||||
}
|
||||
#endif
|
||||
@ -83,7 +83,7 @@ BEGIN_TEST(read0, "acces randomly the entries on a loaded tree")
|
||||
must_be_true(git_tree_entry_byindex(tree, 3) == NULL);
|
||||
must_be_true(git_tree_entry_byindex(tree, (unsigned int)-1) == NULL);
|
||||
|
||||
git_tree_close(tree);
|
||||
git_tree_free(tree);
|
||||
git_repository_free(repo);
|
||||
END_TEST
|
||||
|
||||
@ -105,7 +105,7 @@ BEGIN_TEST(read1, "read a tree from the repository")
|
||||
/* GH-86: git_object_lookup() should also check the type if the object comes from the cache */
|
||||
must_be_true(git_object_lookup(&obj, repo, &id, GIT_OBJ_TREE) == 0);
|
||||
must_be_true(obj != NULL);
|
||||
git_object_close(obj);
|
||||
git_object_free(obj);
|
||||
obj = NULL;
|
||||
must_be_true(git_object_lookup(&obj, repo, &id, GIT_OBJ_BLOB) == GIT_EINVALIDTYPE);
|
||||
must_be_true(obj == NULL);
|
||||
@ -118,8 +118,8 @@ BEGIN_TEST(read1, "read a tree from the repository")
|
||||
must_pass(git_tree_entry_2object(&obj, repo, entry));
|
||||
must_be_true(obj != NULL);
|
||||
|
||||
git_object_close(obj);
|
||||
git_tree_close(tree);
|
||||
git_object_free(obj);
|
||||
git_tree_free(tree);
|
||||
git_repository_free(repo);
|
||||
END_TEST
|
||||
|
||||
@ -164,7 +164,7 @@ BEGIN_TEST(write2, "write a tree from a memory")
|
||||
must_be_true(git_oid_cmp(&rid, &id2) == 0);
|
||||
|
||||
git_treebuilder_free(builder);
|
||||
git_tree_close(tree);
|
||||
git_tree_free(tree);
|
||||
close_temp_repo(repo);
|
||||
END_TEST
|
||||
|
||||
@ -193,7 +193,7 @@ BEGIN_TEST(write3, "write a hierarchical tree from a memory")
|
||||
must_pass(git_treebuilder_insert(NULL,builder,"new",&subtree_id,040000));
|
||||
must_pass(git_treebuilder_write(&id_hiearar,repo,builder));
|
||||
git_treebuilder_free(builder);
|
||||
git_tree_close(tree);
|
||||
git_tree_free(tree);
|
||||
|
||||
must_be_true(git_oid_cmp(&id_hiearar, &id3) == 0);
|
||||
|
||||
@ -204,7 +204,7 @@ BEGIN_TEST(write3, "write a hierarchical tree from a memory")
|
||||
must_be_true((loose_object_dir_mode(TEMP_REPO_FOLDER, (git_object *)tree) & 0777) == GIT_OBJECT_DIR_MODE);
|
||||
must_be_true((loose_object_mode(TEMP_REPO_FOLDER, (git_object *)tree) & 0777) == GIT_OBJECT_FILE_MODE);
|
||||
#endif
|
||||
git_tree_close(tree);
|
||||
git_tree_free(tree);
|
||||
|
||||
close_temp_repo(repo);
|
||||
|
||||
|
||||
@ -54,7 +54,7 @@ BEGIN_TEST(readtag0, "lookup a loose tag reference")
|
||||
git_path_join(ref_name_from_tag_name, GIT_REFS_TAGS_DIR, git_tag_name((git_tag *)object));
|
||||
must_be_true(strcmp(ref_name_from_tag_name, loose_tag_ref_name) == 0);
|
||||
|
||||
git_object_close(object);
|
||||
git_object_free(object);
|
||||
git_repository_free(repo);
|
||||
|
||||
git_reference_free(reference);
|
||||
@ -99,7 +99,7 @@ BEGIN_TEST(readsym0, "lookup a symbolic reference")
|
||||
git_oid_fromstr(&id, current_master_tip);
|
||||
must_be_true(git_oid_cmp(&id, git_object_id(object)) == 0);
|
||||
|
||||
git_object_close(object);
|
||||
git_object_free(object);
|
||||
git_repository_free(repo);
|
||||
|
||||
git_reference_free(reference);
|
||||
@ -129,7 +129,7 @@ BEGIN_TEST(readsym1, "lookup a nested symbolic reference")
|
||||
git_oid_fromstr(&id, current_master_tip);
|
||||
must_be_true(git_oid_cmp(&id, git_object_id(object)) == 0);
|
||||
|
||||
git_object_close(object);
|
||||
git_object_free(object);
|
||||
git_repository_free(repo);
|
||||
|
||||
git_reference_free(reference);
|
||||
@ -200,7 +200,7 @@ BEGIN_TEST(readpacked0, "lookup a packed reference")
|
||||
must_be_true(object != NULL);
|
||||
must_be_true(git_object_type(object) == GIT_OBJ_COMMIT);
|
||||
|
||||
git_object_close(object);
|
||||
git_object_free(object);
|
||||
git_repository_free(repo);
|
||||
|
||||
git_reference_free(reference);
|
||||
|
||||
291
tests/t12-repo.c
291
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
|
||||
|
||||
|
||||
@ -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
|
||||
@ -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
|
||||
@ -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),
|
||||
};
|
||||
|
||||
Loading…
Reference in New Issue
Block a user