mirror of
https://git.proxmox.com/git/libgit2
synced 2025-05-29 06:20:56 +00:00
Merge remote-tracking branch 'upstream/development' into config
This commit is contained in:
commit
8bd6c0ab83
@ -85,8 +85,8 @@ The waf build system for libgit2 accepts the following flags:
|
||||
--arch=[ia64|x64|x86|x86_amd64|x86_ia64]
|
||||
Force a specific architecture for compilers that support it.
|
||||
|
||||
--without-sqlite
|
||||
Disable sqlite support.
|
||||
--with-sqlite
|
||||
Enable sqlite support.
|
||||
|
||||
You can run `./waf --help` to see a full list of install options and
|
||||
targets.
|
||||
|
@ -140,7 +140,8 @@ GIT_EXTERN(const char *) git_tag_message(git_tag *t);
|
||||
* @param repo Repository where to store the tag
|
||||
*
|
||||
* @param tag_name Name for the tag; this name is validated
|
||||
* for consistency
|
||||
* for consistency. It should also not conflict with an
|
||||
* already existing tag name
|
||||
*
|
||||
* @param target OID to which this tag points; note that no
|
||||
* validation is done on this OID. Use the _o version of this
|
||||
@ -188,6 +189,92 @@ GIT_EXTERN(int) git_tag_create_o(
|
||||
const git_signature *tagger,
|
||||
const char *message);
|
||||
|
||||
/**
|
||||
* Create a new tag in the repository from a buffer
|
||||
*
|
||||
* @param oid Pointer where to store the OID of the newly created tag
|
||||
*
|
||||
* @param repo Repository where to store the tag
|
||||
*
|
||||
* @param buffer Raw tag data
|
||||
*/
|
||||
GIT_EXTERN(int) git_tag_create_frombuffer(
|
||||
git_oid *oid,
|
||||
git_repository *repo,
|
||||
const char *buffer);
|
||||
|
||||
/**
|
||||
* Create a new tag in the repository from an OID
|
||||
* and overwrite an already existing tag reference, if any.
|
||||
*
|
||||
* @param oid Pointer where to store the OID of the
|
||||
* newly created tag
|
||||
*
|
||||
* @param repo Repository where to store the tag
|
||||
*
|
||||
* @param tag_name Name for the tag; this name is validated
|
||||
* for consistency.
|
||||
*
|
||||
* @param target OID to which this tag points; note that no
|
||||
* validation is done on this OID. Use the _fo version of this
|
||||
* method to assure a proper object is being tagged
|
||||
*
|
||||
* @param target_type Type of the tagged OID; note that no
|
||||
* validation is performed here either
|
||||
*
|
||||
* @param tagger Signature of the tagger for this tag, and
|
||||
* of the tagging time
|
||||
*
|
||||
* @param message Full message for this tag
|
||||
*
|
||||
* @return 0 on success; error code otherwise.
|
||||
* A tag object is written to the ODB, and a proper reference
|
||||
* is written in the /refs/tags folder, pointing to it
|
||||
*/
|
||||
GIT_EXTERN(int) git_tag_create_f(
|
||||
git_oid *oid,
|
||||
git_repository *repo,
|
||||
const char *tag_name,
|
||||
const git_oid *target,
|
||||
git_otype target_type,
|
||||
const git_signature *tagger,
|
||||
const char *message);
|
||||
|
||||
/**
|
||||
* Create a new tag in the repository from an existing
|
||||
* `git_object` instance and overwrite an already existing
|
||||
* tag reference, if any.
|
||||
*
|
||||
* This method replaces the `target` and `target_type`
|
||||
* paremeters of `git_tag_create_f` by a single instance
|
||||
* of a `const git_object *`, which is assured to be
|
||||
* a proper object in the ODB and hence will create
|
||||
* a valid tag
|
||||
*
|
||||
* @see git_tag_create_f
|
||||
*/
|
||||
GIT_EXTERN(int) git_tag_create_fo(
|
||||
git_oid *oid,
|
||||
git_repository *repo,
|
||||
const char *tag_name,
|
||||
const git_object *target,
|
||||
const git_signature *tagger,
|
||||
const char *message);
|
||||
|
||||
/**
|
||||
* Delete an existing tag reference.
|
||||
*
|
||||
* @param repo Repository where lives the tag
|
||||
*
|
||||
* @param tag_name Name of the tag to be deleted;
|
||||
* this name is validated for consistency.
|
||||
*
|
||||
* @return 0 on success; error code otherwise.
|
||||
*/
|
||||
GIT_EXTERN(int) git_tag_delete(
|
||||
git_repository *repo,
|
||||
const char *tag_name);
|
||||
|
||||
/** @} */
|
||||
GIT_END_DECL
|
||||
#endif
|
||||
|
@ -93,7 +93,7 @@ GIT_EXTERN(size_t) git_tree_entrycount(git_tree *tree);
|
||||
* @param filename the filename of the desired entry
|
||||
* @return the tree entry; NULL if not found
|
||||
*/
|
||||
GIT_EXTERN(git_tree_entry *) git_tree_entry_byname(git_tree *tree, const char *filename);
|
||||
GIT_EXTERN(const git_tree_entry *) git_tree_entry_byname(git_tree *tree, const char *filename);
|
||||
|
||||
/**
|
||||
* Lookup a tree entry by its position in the tree
|
||||
@ -102,7 +102,7 @@ GIT_EXTERN(git_tree_entry *) git_tree_entry_byname(git_tree *tree, const char *f
|
||||
* @param idx the position in the entry list
|
||||
* @return the tree entry; NULL if not found
|
||||
*/
|
||||
GIT_EXTERN(git_tree_entry *) git_tree_entry_byindex(git_tree *tree, int idx);
|
||||
GIT_EXTERN(const git_tree_entry *) git_tree_entry_byindex(git_tree *tree, int idx);
|
||||
|
||||
/**
|
||||
* Get the UNIX file attributes of a tree entry
|
||||
@ -110,7 +110,7 @@ GIT_EXTERN(git_tree_entry *) git_tree_entry_byindex(git_tree *tree, int idx);
|
||||
* @param entry a tree entry
|
||||
* @return attributes as an integer
|
||||
*/
|
||||
GIT_EXTERN(unsigned int) git_tree_entry_attributes(git_tree_entry *entry);
|
||||
GIT_EXTERN(unsigned int) git_tree_entry_attributes(const git_tree_entry *entry);
|
||||
|
||||
/**
|
||||
* Get the filename of a tree entry
|
||||
@ -118,7 +118,7 @@ GIT_EXTERN(unsigned int) git_tree_entry_attributes(git_tree_entry *entry);
|
||||
* @param entry a tree entry
|
||||
* @return the name of the file
|
||||
*/
|
||||
GIT_EXTERN(const char *) git_tree_entry_name(git_tree_entry *entry);
|
||||
GIT_EXTERN(const char *) git_tree_entry_name(const git_tree_entry *entry);
|
||||
|
||||
/**
|
||||
* Get the id of the object pointed by the entry
|
||||
@ -126,7 +126,7 @@ GIT_EXTERN(const char *) git_tree_entry_name(git_tree_entry *entry);
|
||||
* @param entry a tree entry
|
||||
* @return the oid of the object
|
||||
*/
|
||||
GIT_EXTERN(const git_oid *) git_tree_entry_id(git_tree_entry *entry);
|
||||
GIT_EXTERN(const git_oid *) git_tree_entry_id(const git_tree_entry *entry);
|
||||
|
||||
/**
|
||||
* Convert a tree entry to the git_object it points too.
|
||||
@ -134,9 +134,132 @@ GIT_EXTERN(const git_oid *) git_tree_entry_id(git_tree_entry *entry);
|
||||
* @param object pointer to the converted object
|
||||
* @param repo repository where to lookup the pointed object
|
||||
* @param entry a tree entry
|
||||
* @return a reference to the pointed object in the repository
|
||||
* @return 0 on success; error code otherwise
|
||||
*/
|
||||
GIT_EXTERN(int) git_tree_entry_2object(git_object **object_out, git_repository *repo, git_tree_entry *entry);
|
||||
GIT_EXTERN(int) git_tree_entry_2object(git_object **object_out, git_repository *repo, const git_tree_entry *entry);
|
||||
|
||||
/**
|
||||
* Write a tree to the ODB from the index file
|
||||
*
|
||||
* This method will scan the index and write a representation
|
||||
* of its current state back to disk; it recursively creates
|
||||
* tree objects for each of the subtrees stored in the index,
|
||||
* but only returns the OID of the root tree. This is the OID
|
||||
* that can be used e.g. to create a commit.
|
||||
*
|
||||
* The index instance cannot be bare, and needs to be associated
|
||||
* to an existing repository.
|
||||
*
|
||||
* @param oid Pointer where to store the written tree
|
||||
* @param index Index to write
|
||||
* @return 0 on success; error code otherwise
|
||||
*/
|
||||
GIT_EXTERN(int) git_tree_create_fromindex(git_oid *oid, git_index *index);
|
||||
|
||||
/**
|
||||
* Create a new tree builder.
|
||||
*
|
||||
* The tree builder can be used to create or modify
|
||||
* trees in memory and write them as tree objects to the
|
||||
* database.
|
||||
*
|
||||
* If the `source` parameter is not NULL, the tree builder
|
||||
* will be initialized with the entries of the given tree.
|
||||
*
|
||||
* If the `source` parameter is NULL, the tree builder will
|
||||
* have no entries and will have to be filled manually.
|
||||
*
|
||||
* @param builder_p Pointer where to store the tree builder
|
||||
* @param source Source tree to initialize the builder (optional)
|
||||
* @return 0 on sucess; error code otherwise
|
||||
*/
|
||||
GIT_EXTERN(int) git_treebuilder_create(git_treebuilder **builder_p, const git_tree *source);
|
||||
|
||||
/**
|
||||
* Clear all the entires in the builder
|
||||
*
|
||||
* @param bld Builder to clear
|
||||
*/
|
||||
GIT_EXTERN(void) git_treebuilder_clear(git_treebuilder *bld);
|
||||
|
||||
/**
|
||||
* Free a tree builder
|
||||
*
|
||||
* This will clear all the entries and free to builder.
|
||||
* Failing to free the builder after you're done using it
|
||||
* will result in a memory leak
|
||||
*
|
||||
* @param bld Builder to free
|
||||
*/
|
||||
GIT_EXTERN(void) git_treebuilder_free(git_treebuilder *bld);
|
||||
|
||||
/**
|
||||
* Get an entry from the builder from its filename
|
||||
*
|
||||
* The returned entry is owned by the builder and should
|
||||
* not be freed manually.
|
||||
*
|
||||
* @param bld Tree builder
|
||||
* @param filename Name of the entry
|
||||
* @return pointer to the entry; NULL if not found
|
||||
*/
|
||||
GIT_EXTERN(const git_tree_entry *) git_treebuilder_get(git_treebuilder *bld, const char *filename);
|
||||
|
||||
/**
|
||||
* Add or update an entry to the builder
|
||||
*
|
||||
* Insert a new entry for `filename` in the builder with the
|
||||
* given attributes.
|
||||
*
|
||||
* if an entry named `filename` already exists, its attributes
|
||||
* will be updated with the given ones.
|
||||
*
|
||||
* The optional pointer `entry_out` can be used to retrieve a
|
||||
* pointer to the newly created/updated entry.
|
||||
*
|
||||
* @param entry_out Pointer to store the entry (optional)
|
||||
* @param bld Tree builder
|
||||
* @param filename Filename of the entry
|
||||
* @param id SHA1 oid of the entry
|
||||
* @param attributes Folder attributes of the entry
|
||||
* @return 0 on success; error code otherwise
|
||||
*/
|
||||
GIT_EXTERN(int) git_treebuilder_insert(git_tree_entry **entry_out, git_treebuilder *bld, const char *filename, const git_oid *id, unsigned int attributes);
|
||||
|
||||
/**
|
||||
* Remove an entry from the builder by its filename
|
||||
*
|
||||
* @param bld Tree builder
|
||||
* @param filename Filename of the entry to remove
|
||||
*/
|
||||
GIT_EXTERN(int) git_treebuilder_remove(git_treebuilder *bld, const char *filename);
|
||||
|
||||
/**
|
||||
* Filter the entries in the tree
|
||||
*
|
||||
* The `filter` callback will be called for each entry
|
||||
* in the tree with a pointer to the entry and the
|
||||
* provided `payload`: if the callback returns 1, the
|
||||
* entry will be filtered (removed from the builder).
|
||||
*
|
||||
* @param bld Tree builder
|
||||
* @param filter Callback to filter entries
|
||||
*/
|
||||
GIT_EXTERN(void) git_treebuilder_filter(git_treebuilder *bld, int (*filter)(const git_tree_entry *, void *), void *payload);
|
||||
|
||||
/**
|
||||
* Write the contents of the tree builder as a tree object
|
||||
*
|
||||
* The tree builder will be written to the given `repo`, and
|
||||
* it's identifying SHA1 hash will be stored in the `oid`
|
||||
* pointer.
|
||||
*
|
||||
* @param oid Pointer where to store the written OID
|
||||
* @param repo Repository where to store the object
|
||||
* @param bld Tree builder to write
|
||||
* @return 0 on success; error code otherwise
|
||||
*/
|
||||
GIT_EXTERN(int) git_treebuilder_write(git_oid *oid, git_repository *repo, git_treebuilder *bld);
|
||||
|
||||
/** @} */
|
||||
GIT_END_DECL
|
||||
|
@ -124,6 +124,9 @@ typedef struct git_tree_entry git_tree_entry;
|
||||
/** Representation of a tree object. */
|
||||
typedef struct git_tree git_tree;
|
||||
|
||||
/** Constructor for in-memory trees */
|
||||
typedef struct git_treebuilder git_treebuilder;
|
||||
|
||||
/** Memory representation of an index file. */
|
||||
typedef struct git_index git_index;
|
||||
|
||||
|
@ -235,9 +235,9 @@ int git_commit_create(
|
||||
return error;
|
||||
}
|
||||
|
||||
int commit_parse_buffer(git_commit *commit, void *data, size_t len)
|
||||
int commit_parse_buffer(git_commit *commit, const void *data, size_t len)
|
||||
{
|
||||
char *buffer = (char *)data;
|
||||
const char *buffer = (char *)data;
|
||||
const char *buffer_end = (char *)data + len;
|
||||
|
||||
git_oid parent_oid;
|
||||
|
65
src/odb.c
65
src/odb.c
@ -149,6 +149,69 @@ int git_odb_hash(git_oid *id, const void *data, size_t len, git_otype type)
|
||||
return git_odb__hash_obj(id, hdr, sizeof(hdr), &hdrlen, &raw);
|
||||
}
|
||||
|
||||
/**
|
||||
* FAKE WSTREAM
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
git_odb_stream stream;
|
||||
char *buffer;
|
||||
size_t size, written;
|
||||
git_otype type;
|
||||
} fake_wstream;
|
||||
|
||||
static int fake_wstream__fwrite(git_oid *oid, git_odb_stream *_stream)
|
||||
{
|
||||
fake_wstream *stream = (fake_wstream *)_stream;
|
||||
return _stream->backend->write(oid, _stream->backend, stream->buffer, stream->size, stream->type);
|
||||
}
|
||||
|
||||
static int fake_wstream__write(git_odb_stream *_stream, const char *data, size_t len)
|
||||
{
|
||||
fake_wstream *stream = (fake_wstream *)_stream;
|
||||
|
||||
if (stream->written + len >= stream->size)
|
||||
return GIT_ENOMEM;
|
||||
|
||||
memcpy(stream->buffer + stream->written, data, len);
|
||||
stream->written += len;
|
||||
return GIT_SUCCESS;
|
||||
}
|
||||
|
||||
static void fake_wstream__free(git_odb_stream *_stream)
|
||||
{
|
||||
fake_wstream *stream = (fake_wstream *)_stream;
|
||||
|
||||
free(stream->buffer);
|
||||
free(stream);
|
||||
}
|
||||
|
||||
static int init_fake_wstream(git_odb_stream **stream_p, git_odb_backend *backend, size_t size, git_otype type)
|
||||
{
|
||||
fake_wstream *stream;
|
||||
|
||||
stream = git__calloc(1, sizeof(fake_wstream));
|
||||
if (stream == NULL)
|
||||
return GIT_ENOMEM;
|
||||
|
||||
stream->size = size;
|
||||
stream->type = type;
|
||||
stream->buffer = git__malloc(size);
|
||||
if (stream->buffer == NULL) {
|
||||
free(stream);
|
||||
return GIT_ENOMEM;
|
||||
}
|
||||
|
||||
stream->stream.backend = backend;
|
||||
stream->stream.read = NULL; /* read only */
|
||||
stream->stream.write = &fake_wstream__write;
|
||||
stream->stream.finalize_write = &fake_wstream__fwrite;
|
||||
stream->stream.free = &fake_wstream__free;
|
||||
stream->stream.mode = GIT_STREAM_WRONLY;
|
||||
|
||||
*stream_p = (git_odb_stream *)stream;
|
||||
return GIT_SUCCESS;
|
||||
}
|
||||
|
||||
/***********************************************************
|
||||
*
|
||||
@ -467,6 +530,8 @@ int git_odb_open_wstream(git_odb_stream **stream, git_odb *db, size_t size, git_
|
||||
|
||||
if (b->writestream != NULL)
|
||||
error = b->writestream(stream, b, size, type);
|
||||
else if (b->write != NULL)
|
||||
error = init_fake_wstream(stream, b, size, type);
|
||||
}
|
||||
|
||||
return error;
|
||||
|
@ -118,13 +118,13 @@ char *git_oid_to_string(char *out, size_t n, const git_oid *oid)
|
||||
return out;
|
||||
}
|
||||
|
||||
int git__parse_oid(git_oid *oid, char **buffer_out,
|
||||
int git__parse_oid(git_oid *oid, const char **buffer_out,
|
||||
const char *buffer_end, const char *header)
|
||||
{
|
||||
const size_t sha_len = GIT_OID_HEXSZ;
|
||||
const size_t header_len = strlen(header);
|
||||
|
||||
char *buffer = *buffer_out;
|
||||
const char *buffer = *buffer_out;
|
||||
|
||||
if (buffer + (header_len + sha_len + 1) > buffer_end)
|
||||
return GIT_EOBJCORRUPTED;
|
||||
|
@ -346,7 +346,7 @@ static int repo_init_reinit(repo_init *results)
|
||||
{
|
||||
/* TODO: reinit the repository */
|
||||
results->has_been_reinit = 1;
|
||||
return GIT_SUCCESS;
|
||||
return GIT_ENOTIMPLEMENTED;
|
||||
}
|
||||
|
||||
static int repo_init_createhead(git_repository *repo)
|
||||
|
@ -43,7 +43,7 @@ struct git_repository {
|
||||
* export */
|
||||
void git_object__free(void *object);
|
||||
|
||||
int git__parse_oid(git_oid *oid, char **buffer_out, const char *buffer_end, const char *header);
|
||||
int git__parse_oid(git_oid *oid, const char **buffer_out, const char *buffer_end, const char *header);
|
||||
int git__write_oid(git_odb_stream *src, const char *header, const git_oid *oid);
|
||||
|
||||
#endif
|
||||
|
@ -109,14 +109,14 @@ static int parse_timezone_offset(const char *buffer, int *offset_out)
|
||||
}
|
||||
|
||||
|
||||
int git_signature__parse(git_signature *sig, char **buffer_out,
|
||||
int git_signature__parse(git_signature *sig, const char **buffer_out,
|
||||
const char *buffer_end, const char *header)
|
||||
{
|
||||
const size_t header_len = strlen(header);
|
||||
|
||||
int name_length, email_length;
|
||||
char *buffer = *buffer_out;
|
||||
char *line_end, *name_end, *email_end;
|
||||
const char *buffer = *buffer_out;
|
||||
const char *line_end, *name_end, *email_end;
|
||||
int offset = 0;
|
||||
|
||||
memset(sig, 0x0, sizeof(git_signature));
|
||||
@ -159,7 +159,7 @@ int git_signature__parse(git_signature *sig, char **buffer_out,
|
||||
if (buffer >= line_end)
|
||||
return GIT_EOBJCORRUPTED;
|
||||
|
||||
sig->when.time = strtol(buffer, &buffer, 10);
|
||||
sig->when.time = strtol(buffer, (char **)&buffer, 10);
|
||||
|
||||
if (sig->when.time == 0)
|
||||
return GIT_EOBJCORRUPTED;
|
||||
|
@ -6,7 +6,7 @@
|
||||
#include "repository.h"
|
||||
#include <time.h>
|
||||
|
||||
int git_signature__parse(git_signature *sig, char **buffer_out, const char *buffer_end, const char *header);
|
||||
int git_signature__parse(git_signature *sig, const char **buffer_out, const char *buffer_end, const char *header);
|
||||
int git_signature__write(char **signature, const char *header, const git_signature *sig);
|
||||
|
||||
#endif
|
||||
|
176
src/tag.c
176
src/tag.c
@ -79,7 +79,7 @@ const char *git_tag_message(git_tag *t)
|
||||
return t->message;
|
||||
}
|
||||
|
||||
static int parse_tag_buffer(git_tag *tag, char *buffer, const char *buffer_end)
|
||||
static int parse_tag_buffer(git_tag *tag, const char *buffer, const char *buffer_end)
|
||||
{
|
||||
static const char *tag_types[] = {
|
||||
NULL, "commit\n", "tree\n", "blob\n", "tag\n"
|
||||
@ -130,9 +130,6 @@ static int parse_tag_buffer(git_tag *tag, char *buffer, const char *buffer_end)
|
||||
|
||||
text_len = search - buffer;
|
||||
|
||||
if (tag->tag_name != NULL)
|
||||
free(tag->tag_name);
|
||||
|
||||
tag->tag_name = git__malloc(text_len + 1);
|
||||
memcpy(tag->tag_name, buffer, text_len);
|
||||
tag->tag_name[text_len] = '\0';
|
||||
@ -141,8 +138,11 @@ static int parse_tag_buffer(git_tag *tag, char *buffer, const char *buffer_end)
|
||||
|
||||
tag->tagger = git__malloc(sizeof(git_signature));
|
||||
|
||||
if ((error = git_signature__parse(tag->tagger, &buffer, buffer_end, "tagger ")) != 0)
|
||||
if ((error = git_signature__parse(tag->tagger, &buffer, buffer_end, "tagger ")) != 0) {
|
||||
free(tag->tag_name);
|
||||
git_signature_free(tag->tagger);
|
||||
return error;
|
||||
}
|
||||
|
||||
text_len = buffer_end - ++buffer;
|
||||
|
||||
@ -153,39 +153,61 @@ static int parse_tag_buffer(git_tag *tag, char *buffer, const char *buffer_end)
|
||||
return GIT_SUCCESS;
|
||||
}
|
||||
|
||||
int git_tag_create_o(
|
||||
git_oid *oid,
|
||||
git_repository *repo,
|
||||
const char *tag_name,
|
||||
const git_object *target,
|
||||
const git_signature *tagger,
|
||||
const char *message)
|
||||
static int retreive_tag_reference(git_reference **tag_reference_out, char *ref_name_out, git_repository *repo, const char *tag_name)
|
||||
{
|
||||
return git_tag_create(
|
||||
oid, repo, tag_name,
|
||||
git_object_id(target),
|
||||
git_object_type(target),
|
||||
tagger, message);
|
||||
git_reference *tag_ref;
|
||||
int error;
|
||||
|
||||
git__joinpath(ref_name_out, GIT_REFS_TAGS_DIR, tag_name);
|
||||
error = git_reference_lookup(&tag_ref, repo, ref_name_out);
|
||||
if (error < GIT_SUCCESS)
|
||||
return error;
|
||||
|
||||
*tag_reference_out = tag_ref;
|
||||
|
||||
return GIT_SUCCESS;
|
||||
}
|
||||
|
||||
int git_tag_create(
|
||||
static int tag_create(
|
||||
git_oid *oid,
|
||||
git_repository *repo,
|
||||
const char *tag_name,
|
||||
const git_oid *target,
|
||||
git_otype target_type,
|
||||
const git_signature *tagger,
|
||||
const char *message)
|
||||
const char *message,
|
||||
int allow_ref_overwrite)
|
||||
{
|
||||
size_t final_size = 0;
|
||||
git_odb_stream *stream;
|
||||
|
||||
const char *type_str;
|
||||
char *tagger_str;
|
||||
git_reference *new_ref;
|
||||
|
||||
char ref_name[MAX_GITDIR_TREE_STRUCTURE_PATH_LENGTH];
|
||||
|
||||
int type_str_len, tag_name_len, tagger_str_len, message_len;
|
||||
int error;
|
||||
int error, should_update_ref = 0;
|
||||
|
||||
/** Ensure the tag name doesn't conflict with an already existing
|
||||
reference unless overwriting has explictly been requested **/
|
||||
error = retreive_tag_reference(&new_ref, ref_name, repo, tag_name);
|
||||
|
||||
switch (error) {
|
||||
case GIT_SUCCESS:
|
||||
if (!allow_ref_overwrite)
|
||||
return GIT_EEXISTS;
|
||||
should_update_ref = 1;
|
||||
|
||||
/* Fall trough */
|
||||
|
||||
case GIT_ENOTFOUND:
|
||||
break;
|
||||
|
||||
default:
|
||||
return error;
|
||||
}
|
||||
|
||||
type_str = git_object_type2string(target_type);
|
||||
|
||||
@ -223,16 +245,120 @@ int git_tag_create(
|
||||
error = stream->finalize_write(oid, stream);
|
||||
stream->free(stream);
|
||||
|
||||
if (error == GIT_SUCCESS) {
|
||||
char ref_name[512];
|
||||
git_reference *new_ref;
|
||||
git__joinpath(ref_name, GIT_REFS_TAGS_DIR, tag_name);
|
||||
if (error < GIT_SUCCESS)
|
||||
return error;
|
||||
|
||||
if (!should_update_ref)
|
||||
error = git_reference_create_oid(&new_ref, repo, ref_name, oid);
|
||||
}
|
||||
else
|
||||
error = git_reference_set_oid(new_ref, oid);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
int git_tag_create_frombuffer(git_oid *oid, git_repository *repo, const char *buffer)
|
||||
{
|
||||
git_tag tag;
|
||||
int error;
|
||||
git_object *obj;
|
||||
|
||||
assert(oid && buffer);
|
||||
|
||||
memset(&tag, 0, sizeof(tag));
|
||||
|
||||
if ((error = parse_tag_buffer(&tag, buffer, buffer + strlen(buffer))) < GIT_SUCCESS)
|
||||
return error;
|
||||
|
||||
error = git_object_lookup(&obj, repo, &tag.target, tag.type);
|
||||
if (error < GIT_SUCCESS)
|
||||
goto cleanup;
|
||||
|
||||
error = git_tag_create_o(oid, repo, tag.tag_name, obj, tag.tagger, tag.message);
|
||||
|
||||
git_object_close(obj);
|
||||
|
||||
cleanup:
|
||||
git_signature_free(tag.tagger);
|
||||
free(tag.tag_name);
|
||||
free(tag.message);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
int git_tag_create_o(
|
||||
git_oid *oid,
|
||||
git_repository *repo,
|
||||
const char *tag_name,
|
||||
const git_object *target,
|
||||
const git_signature *tagger,
|
||||
const char *message)
|
||||
{
|
||||
return tag_create(
|
||||
oid, repo, tag_name,
|
||||
git_object_id(target),
|
||||
git_object_type(target),
|
||||
tagger, message, 0);
|
||||
}
|
||||
|
||||
int git_tag_create(
|
||||
git_oid *oid,
|
||||
git_repository *repo,
|
||||
const char *tag_name,
|
||||
const git_oid *target,
|
||||
git_otype target_type,
|
||||
const git_signature *tagger,
|
||||
const char *message)
|
||||
{
|
||||
return tag_create(
|
||||
oid, repo, tag_name,
|
||||
target,
|
||||
target_type,
|
||||
tagger, message, 0);
|
||||
}
|
||||
|
||||
int git_tag_create_fo(
|
||||
git_oid *oid,
|
||||
git_repository *repo,
|
||||
const char *tag_name,
|
||||
const git_object *target,
|
||||
const git_signature *tagger,
|
||||
const char *message)
|
||||
{
|
||||
return tag_create(
|
||||
oid, repo, tag_name,
|
||||
git_object_id(target),
|
||||
git_object_type(target),
|
||||
tagger, message, 1);
|
||||
}
|
||||
|
||||
int git_tag_create_f(
|
||||
git_oid *oid,
|
||||
git_repository *repo,
|
||||
const char *tag_name,
|
||||
const git_oid *target,
|
||||
git_otype target_type,
|
||||
const git_signature *tagger,
|
||||
const char *message)
|
||||
{
|
||||
return tag_create(
|
||||
oid, repo, tag_name,
|
||||
target,
|
||||
target_type,
|
||||
tagger, message, 1);
|
||||
}
|
||||
|
||||
int git_tag_delete(git_repository *repo, const char *tag_name)
|
||||
{
|
||||
int error;
|
||||
git_reference *tag_ref;
|
||||
char ref_name[MAX_GITDIR_TREE_STRUCTURE_PATH_LENGTH];
|
||||
|
||||
error = retreive_tag_reference(&tag_ref, ref_name, repo, tag_name);
|
||||
if (error < GIT_SUCCESS)
|
||||
return error;
|
||||
|
||||
return git_reference_delete(tag_ref);
|
||||
}
|
||||
|
||||
int git_tag__parse(git_tag *tag, git_odb_object *obj)
|
||||
{
|
||||
|
324
src/tree.c
324
src/tree.c
@ -33,6 +33,10 @@
|
||||
#define MAX_FILEMODE 0777777
|
||||
#define MAX_FILEMODE_BYTES 6
|
||||
|
||||
static int valid_attributes(const int attributes) {
|
||||
return attributes >= 0 && attributes <= MAX_FILEMODE;
|
||||
}
|
||||
|
||||
int entry_search_cmp(const void *key, const void *array_member)
|
||||
{
|
||||
const char *filename = (const char *)key;
|
||||
@ -79,30 +83,30 @@ const git_oid *git_tree_id(git_tree *c)
|
||||
return git_object_id((git_object *)c);
|
||||
}
|
||||
|
||||
unsigned int git_tree_entry_attributes(git_tree_entry *entry)
|
||||
unsigned int git_tree_entry_attributes(const git_tree_entry *entry)
|
||||
{
|
||||
return entry->attr;
|
||||
}
|
||||
|
||||
const char *git_tree_entry_name(git_tree_entry *entry)
|
||||
const char *git_tree_entry_name(const git_tree_entry *entry)
|
||||
{
|
||||
assert(entry);
|
||||
return entry->filename;
|
||||
}
|
||||
|
||||
const git_oid *git_tree_entry_id(git_tree_entry *entry)
|
||||
const git_oid *git_tree_entry_id(const git_tree_entry *entry)
|
||||
{
|
||||
assert(entry);
|
||||
return &entry->oid;
|
||||
}
|
||||
|
||||
int git_tree_entry_2object(git_object **object_out, git_repository *repo, git_tree_entry *entry)
|
||||
int git_tree_entry_2object(git_object **object_out, git_repository *repo, const git_tree_entry *entry)
|
||||
{
|
||||
assert(entry && object_out);
|
||||
return git_object_lookup(object_out, repo, &entry->oid, GIT_OBJ_ANY);
|
||||
}
|
||||
|
||||
git_tree_entry *git_tree_entry_byname(git_tree *tree, const char *filename)
|
||||
const git_tree_entry *git_tree_entry_byname(git_tree *tree, const char *filename)
|
||||
{
|
||||
int idx;
|
||||
|
||||
@ -115,7 +119,7 @@ git_tree_entry *git_tree_entry_byname(git_tree *tree, const char *filename)
|
||||
return git_vector_get(&tree->entries, idx);
|
||||
}
|
||||
|
||||
git_tree_entry *git_tree_entry_byindex(git_tree *tree, int idx)
|
||||
const git_tree_entry *git_tree_entry_byindex(git_tree *tree, int idx)
|
||||
{
|
||||
assert(tree);
|
||||
return git_vector_get(&tree->entries, (unsigned int)idx);
|
||||
@ -127,7 +131,7 @@ size_t git_tree_entrycount(git_tree *tree)
|
||||
return tree->entries.length;
|
||||
}
|
||||
|
||||
static int tree_parse_buffer(git_tree *tree, char *buffer, char *buffer_end)
|
||||
static int tree_parse_buffer(git_tree *tree, const char *buffer, const char *buffer_end)
|
||||
{
|
||||
int error = GIT_SUCCESS;
|
||||
|
||||
@ -137,7 +141,7 @@ static int tree_parse_buffer(git_tree *tree, char *buffer, char *buffer_end)
|
||||
while (buffer < buffer_end) {
|
||||
git_tree_entry *entry;
|
||||
|
||||
entry = git__malloc(sizeof(git_tree_entry));
|
||||
entry = git__calloc(1, sizeof(git_tree_entry));
|
||||
if (entry == NULL) {
|
||||
error = GIT_ENOMEM;
|
||||
break;
|
||||
@ -146,7 +150,7 @@ static int tree_parse_buffer(git_tree *tree, char *buffer, char *buffer_end)
|
||||
if (git_vector_insert(&tree->entries, entry) < GIT_SUCCESS)
|
||||
return GIT_ENOMEM;
|
||||
|
||||
entry->attr = strtol(buffer, &buffer, 8);
|
||||
entry->attr = strtol(buffer, (char **)&buffer, 8);
|
||||
|
||||
if (*buffer++ != ' ') {
|
||||
error = GIT_EOBJCORRUPTED;
|
||||
@ -159,6 +163,7 @@ static int tree_parse_buffer(git_tree *tree, char *buffer, char *buffer_end)
|
||||
}
|
||||
|
||||
entry->filename = git__strdup(buffer);
|
||||
entry->filename_len = strlen(buffer);
|
||||
|
||||
while (buffer < buffer_end && *buffer != 0)
|
||||
buffer++;
|
||||
@ -178,3 +183,304 @@ int git_tree__parse(git_tree *tree, git_odb_object *obj)
|
||||
return tree_parse_buffer(tree, (char *)obj->raw.data, (char *)obj->raw.data + obj->raw.len);
|
||||
}
|
||||
|
||||
static int write_index_entry(char *buffer, int mode, const char *path, size_t path_len, const git_oid *oid)
|
||||
{
|
||||
int written;
|
||||
written = sprintf(buffer, "%o %.*s%c", mode, (int)path_len, path, 0);
|
||||
memcpy(buffer + written, &oid->id, GIT_OID_RAWSZ);
|
||||
return written + GIT_OID_RAWSZ;
|
||||
}
|
||||
|
||||
static int write_index(git_oid *oid, git_index *index, const char *base, int baselen, int entry_no, int maxentries)
|
||||
{
|
||||
size_t size, offset;
|
||||
char *buffer;
|
||||
int nr, error;
|
||||
|
||||
/* Guess at some random initial size */
|
||||
size = maxentries * 40;
|
||||
buffer = git__malloc(size);
|
||||
if (buffer == NULL)
|
||||
return GIT_ENOMEM;
|
||||
|
||||
offset = 0;
|
||||
|
||||
for (nr = entry_no; nr < maxentries; ++nr) {
|
||||
git_index_entry *entry = git_index_get(index, nr);
|
||||
|
||||
const char *pathname = entry->path, *filename, *dirname;
|
||||
int pathlen = strlen(pathname), entrylen;
|
||||
|
||||
unsigned int write_mode;
|
||||
git_oid subtree_oid;
|
||||
git_oid *write_oid;
|
||||
|
||||
/* Did we hit the end of the directory? Return how many we wrote */
|
||||
if (baselen >= pathlen || memcmp(base, pathname, baselen) != 0)
|
||||
break;
|
||||
|
||||
/* Do we have _further_ subdirectories? */
|
||||
filename = pathname + baselen;
|
||||
dirname = strchr(filename, '/');
|
||||
|
||||
write_oid = &entry->oid;
|
||||
write_mode = entry->mode;
|
||||
|
||||
if (dirname) {
|
||||
int subdir_written;
|
||||
|
||||
#if 0
|
||||
if (entry->mode != S_IFDIR) {
|
||||
free(buffer);
|
||||
return GIT_EOBJCORRUPTED;
|
||||
}
|
||||
#endif
|
||||
subdir_written = write_index(&subtree_oid, index, pathname, dirname - pathname + 1, nr, maxentries);
|
||||
|
||||
if (subdir_written < GIT_SUCCESS) {
|
||||
free(buffer);
|
||||
return subdir_written;
|
||||
}
|
||||
|
||||
nr = subdir_written - 1;
|
||||
|
||||
/* Now we need to write out the directory entry into this tree.. */
|
||||
pathlen = dirname - pathname;
|
||||
write_oid = &subtree_oid;
|
||||
write_mode = S_IFDIR;
|
||||
}
|
||||
|
||||
entrylen = pathlen - baselen;
|
||||
if (offset + entrylen + 32 > size) {
|
||||
size = alloc_nr(offset + entrylen + 32);
|
||||
buffer = git__realloc(buffer, size);
|
||||
|
||||
if (buffer == NULL)
|
||||
return GIT_ENOMEM;
|
||||
}
|
||||
|
||||
offset += write_index_entry(buffer + offset, write_mode, filename, entrylen, write_oid);
|
||||
}
|
||||
|
||||
error = git_odb_write(oid, index->repository->db, buffer, offset, GIT_OBJ_TREE);
|
||||
free(buffer);
|
||||
|
||||
return (error == GIT_SUCCESS) ? nr : error;
|
||||
}
|
||||
|
||||
int git_tree_create_fromindex(git_oid *oid, git_index *index)
|
||||
{
|
||||
int error;
|
||||
|
||||
if (index->repository == NULL)
|
||||
return GIT_EBAREINDEX;
|
||||
|
||||
error = write_index(oid, index, "", 0, 0, git_index_entrycount(index));
|
||||
return (error < GIT_SUCCESS) ? error : GIT_SUCCESS;
|
||||
}
|
||||
|
||||
static void sort_entries(git_treebuilder *bld)
|
||||
{
|
||||
git_vector_sort(&bld->entries);
|
||||
}
|
||||
|
||||
int git_treebuilder_create(git_treebuilder **builder_p, const git_tree *source)
|
||||
{
|
||||
git_treebuilder *bld;
|
||||
size_t i, source_entries = DEFAULT_TREE_SIZE;
|
||||
|
||||
assert(builder_p);
|
||||
|
||||
bld = git__calloc(1, sizeof(git_treebuilder));
|
||||
if (bld == NULL)
|
||||
return GIT_ENOMEM;
|
||||
|
||||
if (source != NULL)
|
||||
source_entries = source->entries.length;
|
||||
|
||||
if (git_vector_init(&bld->entries, source_entries, entry_sort_cmp) < GIT_SUCCESS) {
|
||||
free(bld);
|
||||
return GIT_ENOMEM;
|
||||
}
|
||||
|
||||
if (source != NULL) {
|
||||
bld->entry_count = source_entries;
|
||||
for (i = 0; i < source->entries.length; ++i) {
|
||||
git_tree_entry *entry_src = source->entries.contents[i];
|
||||
git_tree_entry *entry = git__calloc(1, sizeof(git_tree_entry));
|
||||
|
||||
if (entry == NULL) {
|
||||
git_treebuilder_free(bld);
|
||||
return GIT_ENOMEM;
|
||||
}
|
||||
|
||||
entry->filename = git__strdup(entry_src->filename);
|
||||
|
||||
if (entry->filename == NULL) {
|
||||
free(entry);
|
||||
git_treebuilder_free(bld);
|
||||
return GIT_ENOMEM;
|
||||
}
|
||||
|
||||
entry->filename_len = entry_src->filename_len;
|
||||
git_oid_cpy(&entry->oid, &entry_src->oid);
|
||||
entry->attr = entry_src->attr;
|
||||
|
||||
git_vector_insert(&bld->entries, entry);
|
||||
}
|
||||
}
|
||||
|
||||
*builder_p = bld;
|
||||
return GIT_SUCCESS;
|
||||
}
|
||||
|
||||
int git_treebuilder_insert(git_tree_entry **entry_out, git_treebuilder *bld, const char *filename, const git_oid *id, unsigned int attributes)
|
||||
{
|
||||
git_tree_entry *entry;
|
||||
int pos;
|
||||
|
||||
assert(bld && id && filename);
|
||||
|
||||
if (!valid_attributes(attributes))
|
||||
return GIT_ERROR;
|
||||
|
||||
if ((pos = git_vector_bsearch2(&bld->entries, entry_search_cmp, filename)) != GIT_ENOTFOUND) {
|
||||
entry = git_vector_get(&bld->entries, pos);
|
||||
if (entry->removed) {
|
||||
entry->removed = 0;
|
||||
bld->entry_count++;
|
||||
}
|
||||
} else {
|
||||
if ((entry = git__malloc(sizeof(git_tree_entry))) == NULL)
|
||||
return GIT_ENOMEM;
|
||||
|
||||
memset(entry, 0x0, sizeof(git_tree_entry));
|
||||
entry->filename = git__strdup(filename);
|
||||
entry->filename_len = strlen(entry->filename);
|
||||
|
||||
bld->entry_count++;
|
||||
}
|
||||
|
||||
git_oid_cpy(&entry->oid, id);
|
||||
entry->attr = attributes;
|
||||
|
||||
if (pos != GIT_ENOTFOUND) {
|
||||
if (git_vector_insert(&bld->entries, entry) < 0)
|
||||
return GIT_ENOMEM;
|
||||
}
|
||||
|
||||
if (entry_out != NULL)
|
||||
*entry_out = entry;
|
||||
|
||||
return GIT_SUCCESS;
|
||||
}
|
||||
|
||||
const git_tree_entry *git_treebuilder_get(git_treebuilder *bld, const char *filename)
|
||||
{
|
||||
int idx;
|
||||
git_tree_entry *entry;
|
||||
|
||||
assert(bld && filename);
|
||||
|
||||
sort_entries(bld);
|
||||
idx = git_vector_bsearch2(&bld->entries, entry_search_cmp, filename);
|
||||
if (idx == GIT_ENOTFOUND)
|
||||
return NULL;
|
||||
|
||||
entry = git_vector_get(&bld->entries, idx);
|
||||
if (entry->removed)
|
||||
return NULL;
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
||||
int git_treebuilder_remove(git_treebuilder *bld, const char *filename)
|
||||
{
|
||||
git_tree_entry *remove_ptr = (git_tree_entry *)git_treebuilder_get(bld, filename);
|
||||
|
||||
if (remove_ptr == NULL || remove_ptr->removed)
|
||||
return GIT_ENOTFOUND;
|
||||
|
||||
remove_ptr->removed = 1;
|
||||
bld->entry_count--;
|
||||
return GIT_SUCCESS;
|
||||
}
|
||||
|
||||
int git_treebuilder_write(git_oid *oid, git_repository *repo, git_treebuilder *bld)
|
||||
{
|
||||
size_t i, size = 0;
|
||||
char filemode[MAX_FILEMODE_BYTES + 1 + 1];
|
||||
git_odb_stream *stream;
|
||||
int error;
|
||||
|
||||
assert(bld);
|
||||
|
||||
sort_entries(bld);
|
||||
|
||||
for (i = 0; i < bld->entries.length; ++i) {
|
||||
git_tree_entry *entry = bld->entries.contents[i];
|
||||
|
||||
if (entry->removed)
|
||||
continue;
|
||||
|
||||
size += (entry->attr > 0x7FF) ? 7 : 6;
|
||||
size += entry->filename_len + 1;
|
||||
size += GIT_OID_RAWSZ;
|
||||
}
|
||||
|
||||
if ((error = git_odb_open_wstream(&stream, git_repository_database(repo), size, GIT_OBJ_TREE)) < GIT_SUCCESS)
|
||||
return error;
|
||||
|
||||
for (i = 0; i < bld->entries.length; ++i) {
|
||||
git_tree_entry *entry = bld->entries.contents[i];
|
||||
|
||||
if (entry->removed)
|
||||
continue;
|
||||
|
||||
snprintf(filemode, sizeof(filemode), "%o ", entry->attr);
|
||||
stream->write(stream, filemode, strlen(filemode));
|
||||
stream->write(stream, entry->filename, entry->filename_len + 1);
|
||||
stream->write(stream, (char *)entry->oid.id, GIT_OID_RAWSZ);
|
||||
}
|
||||
|
||||
error = stream->finalize_write(oid, stream);
|
||||
stream->free(stream);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
void git_treebuilder_filter(git_treebuilder *bld, int (*filter)(const git_tree_entry *, void *), void *payload)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
assert(bld && filter);
|
||||
|
||||
for (i = 0; i < bld->entries.length; ++i) {
|
||||
git_tree_entry *entry = bld->entries.contents[i];
|
||||
if (!entry->removed && filter(entry, payload))
|
||||
entry->removed = 1;
|
||||
}
|
||||
}
|
||||
|
||||
void git_treebuilder_clear(git_treebuilder *bld)
|
||||
{
|
||||
size_t i;
|
||||
assert(bld);
|
||||
|
||||
for (i = 0; i < bld->entries.length; ++i) {
|
||||
git_tree_entry *e = bld->entries.contents[i];
|
||||
free(e->filename);
|
||||
free(e);
|
||||
}
|
||||
|
||||
git_vector_clear(&bld->entries);
|
||||
}
|
||||
|
||||
void git_treebuilder_free(git_treebuilder *bld)
|
||||
{
|
||||
git_treebuilder_clear(bld);
|
||||
git_vector_free(&bld->entries);
|
||||
free(bld);
|
||||
}
|
||||
|
||||
|
||||
|
@ -10,6 +10,8 @@ struct git_tree_entry {
|
||||
unsigned int attr;
|
||||
char *filename;
|
||||
git_oid oid;
|
||||
size_t filename_len;
|
||||
int removed;
|
||||
};
|
||||
|
||||
struct git_tree {
|
||||
@ -17,6 +19,12 @@ struct git_tree {
|
||||
git_vector entries;
|
||||
};
|
||||
|
||||
struct git_treebuilder {
|
||||
git_vector entries;
|
||||
size_t entry_count;
|
||||
};
|
||||
|
||||
|
||||
void git_tree__free(git_tree *tree);
|
||||
int git_tree__parse(git_tree *tree, git_odb_object *obj);
|
||||
|
||||
|
@ -14,6 +14,7 @@
|
||||
*/
|
||||
#define git__malloc malloc
|
||||
#define git__calloc calloc
|
||||
#define git__realloc realloc
|
||||
#define git__strdup strdup
|
||||
|
||||
extern int git__fmt(char *, size_t, const char *, ...)
|
||||
|
@ -114,15 +114,15 @@ BEGIN_TEST(parse0, "parse the OID line in a commit")
|
||||
git_oid oid;
|
||||
|
||||
#define TEST_OID_PASS(string, header) { \
|
||||
char *ptr = string;\
|
||||
char *ptr_original = ptr;\
|
||||
const char *ptr = string;\
|
||||
const char *ptr_original = ptr;\
|
||||
size_t len = strlen(ptr);\
|
||||
must_pass(git__parse_oid(&oid, &ptr, ptr + len, header));\
|
||||
must_be_true(ptr == ptr_original + len);\
|
||||
}
|
||||
|
||||
#define TEST_OID_FAIL(string, header) { \
|
||||
char *ptr = string;\
|
||||
const char *ptr = string;\
|
||||
size_t len = strlen(ptr);\
|
||||
must_fail(git__parse_oid(&oid, &ptr, ptr + len, header));\
|
||||
}
|
||||
@ -154,7 +154,7 @@ END_TEST
|
||||
BEGIN_TEST(parse1, "parse the signature line in a commit")
|
||||
|
||||
#define TEST_SIGNATURE_PASS(_string, _header, _name, _email, _time, _offset) { \
|
||||
char *ptr = _string; \
|
||||
const char *ptr = _string; \
|
||||
size_t len = strlen(_string);\
|
||||
git_signature person = {NULL, NULL, {0, 0}}; \
|
||||
must_pass(git_signature__parse(&person, &ptr, ptr + len, _header));\
|
||||
@ -166,7 +166,7 @@ BEGIN_TEST(parse1, "parse the signature line in a commit")
|
||||
}
|
||||
|
||||
#define TEST_SIGNATURE_FAIL(_string, _header) { \
|
||||
char *ptr = _string; \
|
||||
const char *ptr = _string; \
|
||||
size_t len = strlen(_string);\
|
||||
git_signature person = {NULL, NULL, {0, 0}}; \
|
||||
must_fail(git_signature__parse(&person, &ptr, ptr + len, _header));\
|
||||
|
133
tests/t08-tag.c
133
tests/t08-tag.c
@ -58,6 +58,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_repository_free(repo);
|
||||
END_TEST
|
||||
|
||||
@ -72,20 +75,19 @@ BEGIN_TEST(write0, "write a tag to the repository and read it again")
|
||||
git_oid target_id, tag_id;
|
||||
const git_signature *tagger;
|
||||
git_reference *ref_tag;
|
||||
/* char hex_oid[41]; */
|
||||
|
||||
must_pass(git_repository_open(&repo, REPOSITORY_FOLDER));
|
||||
|
||||
git_oid_mkstr(&target_id, tagged_commit);
|
||||
|
||||
/* create signatures */
|
||||
/* create signature */
|
||||
tagger = git_signature_new(TAGGER_NAME, TAGGER_EMAIL, 123456789, 60);
|
||||
must_be_true(tagger != NULL);
|
||||
|
||||
must_pass(git_tag_create(
|
||||
&tag_id, /* out id */
|
||||
repo,
|
||||
"the-tag", /* do not update the HEAD */
|
||||
"the-tag",
|
||||
&target_id,
|
||||
GIT_OBJ_COMMIT,
|
||||
tagger,
|
||||
@ -94,6 +96,7 @@ BEGIN_TEST(write0, "write a tag to the repository and read it again")
|
||||
git_signature_free((git_signature *)tagger);
|
||||
|
||||
must_pass(git_tag_lookup(&tag, repo, &tag_id));
|
||||
must_be_true(git_oid_cmp(git_tag_target_oid(tag), &target_id) == 0);
|
||||
|
||||
/* Check attributes were set correctly */
|
||||
tagger = git_tag_tagger(tag);
|
||||
@ -111,12 +114,136 @@ 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_repository_free(repo);
|
||||
|
||||
END_TEST
|
||||
|
||||
BEGIN_TEST(write1, "write a tag to the repository which points to an unknown oid and read it again")
|
||||
git_repository *repo;
|
||||
git_tag *tag;
|
||||
git_oid target_id, tag_id;
|
||||
const git_signature *tagger;
|
||||
git_reference *ref_tag;
|
||||
git_object *zombie;
|
||||
|
||||
must_pass(git_repository_open(&repo, REPOSITORY_FOLDER));
|
||||
|
||||
git_oid_mkstr(&target_id, "deadbeef1b46c854b31185ea97743be6a8774479");
|
||||
|
||||
/* create signature */
|
||||
tagger = git_signature_new(TAGGER_NAME, TAGGER_EMAIL, 123456789, 60);
|
||||
must_be_true(tagger != NULL);
|
||||
|
||||
must_pass(git_tag_create(
|
||||
&tag_id, /* out id */
|
||||
repo,
|
||||
"the-zombie-tag",
|
||||
&target_id,
|
||||
GIT_OBJ_COMMIT,
|
||||
tagger,
|
||||
TAGGER_MESSAGE));
|
||||
|
||||
git_signature_free((git_signature *)tagger);
|
||||
|
||||
must_pass(git_tag_lookup(&tag, repo, &tag_id));
|
||||
|
||||
/* The non existent target can not be looked up */
|
||||
must_fail(git_tag_target(&zombie, tag));
|
||||
|
||||
must_pass(git_reference_lookup(&ref_tag, repo, "refs/tags/the-zombie-tag"));
|
||||
|
||||
must_pass(git_reference_delete(ref_tag));
|
||||
must_pass(remove_loose_object(REPOSITORY_FOLDER, (git_object *)tag));
|
||||
|
||||
git_tag_close(tag);
|
||||
git_repository_free(repo);
|
||||
|
||||
END_TEST
|
||||
|
||||
BEGIN_TEST(write2, "Attempt to write a tag bearing the same name than an already existing tag")
|
||||
git_repository *repo;
|
||||
git_oid target_id, tag_id;
|
||||
const git_signature *tagger;
|
||||
|
||||
must_pass(git_repository_open(&repo, REPOSITORY_FOLDER));
|
||||
|
||||
git_oid_mkstr(&target_id, tagged_commit);
|
||||
|
||||
/* create signature */
|
||||
tagger = git_signature_new(TAGGER_NAME, TAGGER_EMAIL, 123456789, 60);
|
||||
must_be_true(tagger != NULL);
|
||||
|
||||
must_fail(git_tag_create(
|
||||
&tag_id, /* out id */
|
||||
repo,
|
||||
"e90810b",
|
||||
&target_id,
|
||||
GIT_OBJ_COMMIT,
|
||||
tagger,
|
||||
TAGGER_MESSAGE));
|
||||
|
||||
git_signature_free((git_signature *)tagger);
|
||||
|
||||
git_repository_free(repo);
|
||||
|
||||
END_TEST
|
||||
|
||||
BEGIN_TEST(write3, "Replace an already existing tag")
|
||||
git_repository *repo;
|
||||
git_oid target_id, tag_id, old_tag_id;
|
||||
const git_signature *tagger;
|
||||
git_reference *ref_tag;
|
||||
|
||||
must_pass(open_temp_repo(&repo, REPOSITORY_FOLDER));
|
||||
|
||||
git_oid_mkstr(&target_id, tagged_commit);
|
||||
|
||||
must_pass(git_reference_lookup(&ref_tag, repo, "refs/tags/e90810b"));
|
||||
git_oid_cpy(&old_tag_id, git_reference_oid(ref_tag));
|
||||
|
||||
/* create signature */
|
||||
tagger = git_signature_new(TAGGER_NAME, TAGGER_EMAIL, 123456789, 60);
|
||||
must_be_true(tagger != NULL);
|
||||
|
||||
must_pass(git_tag_create_f(
|
||||
&tag_id, /* out id */
|
||||
repo,
|
||||
"e90810b",
|
||||
&target_id,
|
||||
GIT_OBJ_COMMIT,
|
||||
tagger,
|
||||
TAGGER_MESSAGE));
|
||||
|
||||
git_signature_free((git_signature *)tagger);
|
||||
|
||||
must_pass(git_reference_lookup(&ref_tag, repo, "refs/tags/e90810b"));
|
||||
must_be_true(git_oid_cmp(git_reference_oid(ref_tag), &tag_id) == 0);
|
||||
must_be_true(git_oid_cmp(git_reference_oid(ref_tag), &old_tag_id) != 0);
|
||||
|
||||
close_temp_repo(repo);
|
||||
|
||||
END_TEST
|
||||
|
||||
BEGIN_TEST(write4, "Delete an already existing tag")
|
||||
git_repository *repo;
|
||||
git_reference *ref_tag;
|
||||
|
||||
must_pass(open_temp_repo(&repo, REPOSITORY_FOLDER));
|
||||
|
||||
must_pass(git_tag_delete(repo,"e90810b"));
|
||||
|
||||
must_fail(git_reference_lookup(&ref_tag, repo, "refs/tags/e90810b"));
|
||||
|
||||
close_temp_repo(repo);
|
||||
|
||||
END_TEST
|
||||
|
||||
BEGIN_SUITE(tag)
|
||||
ADD_TEST(read0);
|
||||
ADD_TEST(write0);
|
||||
ADD_TEST(write1);
|
||||
ADD_TEST(write2);
|
||||
ADD_TEST(write3);
|
||||
ADD_TEST(write4);
|
||||
END_SUITE
|
||||
|
@ -29,6 +29,36 @@
|
||||
|
||||
static const char *tree_oid = "1810dff58d8a660512d4832e740f692884338ccd";
|
||||
|
||||
#if 0
|
||||
static int print_tree(git_repository *repo, const git_oid *tree_oid, int depth)
|
||||
{
|
||||
static const char *indent = " ";
|
||||
git_tree *tree;
|
||||
unsigned int i;
|
||||
|
||||
if (git_tree_lookup(&tree, repo, tree_oid) < GIT_SUCCESS)
|
||||
return GIT_ERROR;
|
||||
|
||||
for (i = 0; i < git_tree_entrycount(tree); ++i) {
|
||||
const git_tree_entry *entry = git_tree_entry_byindex(tree, i);
|
||||
char entry_oid[40];
|
||||
|
||||
git_oid_fmt(entry_oid, &entry->oid);
|
||||
printf("%.*s%o [%.*s] %s\n", depth*2, indent, entry->attr, 40, entry_oid, entry->filename);
|
||||
|
||||
if (entry->attr == S_IFDIR) {
|
||||
if (print_tree(repo, &entry->oid, depth + 1) < GIT_SUCCESS) {
|
||||
git_tree_close(tree);
|
||||
return GIT_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
git_tree_close(tree);
|
||||
return GIT_SUCCESS;
|
||||
}
|
||||
#endif
|
||||
|
||||
BEGIN_TEST(read0, "acces randomly the entries on a loaded tree")
|
||||
git_oid id;
|
||||
git_repository *repo;
|
||||
@ -55,7 +85,7 @@ BEGIN_TEST(read1, "read a tree from the repository")
|
||||
git_oid id;
|
||||
git_repository *repo;
|
||||
git_tree *tree;
|
||||
git_tree_entry *entry;
|
||||
const git_tree_entry *entry;
|
||||
git_object *obj;
|
||||
|
||||
must_pass(git_repository_open(&repo, REPOSITORY_FOLDER));
|
||||
@ -80,10 +110,27 @@ BEGIN_TEST(read1, "read a tree from the repository")
|
||||
git_repository_free(repo);
|
||||
END_TEST
|
||||
|
||||
#if 0
|
||||
BEGIN_TEST(write0, "write a tree from an index")
|
||||
git_repository *repo;
|
||||
git_index *index;
|
||||
git_oid tree_oid;
|
||||
|
||||
must_pass(git_repository_open(&repo, "/tmp/redtmp/.git"));
|
||||
must_pass(git_repository_index(&index, repo));
|
||||
|
||||
must_pass(git_tree_create_fromindex(&tree_oid, index));
|
||||
must_pass(print_tree(repo, &tree_oid, 0));
|
||||
|
||||
git_repository_free(repo);
|
||||
END_TEST
|
||||
#endif
|
||||
|
||||
BEGIN_SUITE(tree)
|
||||
//ADD_TEST(print0);
|
||||
ADD_TEST(read0);
|
||||
ADD_TEST(read1);
|
||||
// ADD_TEST(write0); /* TODO THREADSAFE */
|
||||
// ADD_TEST(write1);
|
||||
//ADD_TEST(write0);
|
||||
//ADD_TEST(write1);
|
||||
END_SUITE
|
||||
|
||||
|
@ -27,13 +27,14 @@
|
||||
|
||||
#include "repository.h"
|
||||
|
||||
static const char *loose_tag_ref_name = "refs/tags/test";
|
||||
static const char *loose_tag_ref_name = "refs/tags/e90810b";
|
||||
static const char *non_existing_tag_ref_name = "refs/tags/i-do-not-exist";
|
||||
|
||||
BEGIN_TEST(readtag0, "lookup a loose tag reference")
|
||||
git_repository *repo;
|
||||
git_reference *reference;
|
||||
git_object *object;
|
||||
char ref_name_from_tag_name[MAX_GITDIR_TREE_STRUCTURE_PATH_LENGTH];
|
||||
|
||||
must_pass(git_repository_open(&repo, REPOSITORY_FOLDER));
|
||||
|
||||
@ -46,6 +47,10 @@ BEGIN_TEST(readtag0, "lookup a loose tag reference")
|
||||
must_be_true(object != NULL);
|
||||
must_be_true(git_object_type(object) == GIT_OBJ_TAG);
|
||||
|
||||
/* Ensure the name of the tag matches the name of the reference */
|
||||
git__joinpath(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_repository_free(repo);
|
||||
END_TEST
|
||||
|
||||
@ -227,9 +232,8 @@ BEGIN_TEST(create0, "create a new symbolic reference")
|
||||
must_pass(git_reference_resolve(&resolved_ref, looked_up_ref));
|
||||
must_be_true(git_oid_cmp(&id, git_reference_oid(resolved_ref)) == 0);
|
||||
|
||||
git_reference_delete(looked_up_ref);
|
||||
git_repository_free(repo);
|
||||
|
||||
must_pass(gitfo_unlink(ref_path)); /* TODO: replace with git_reference_delete() when available */
|
||||
END_TEST
|
||||
|
||||
BEGIN_TEST(create1, "create a deep symbolic reference")
|
||||
@ -250,9 +254,8 @@ BEGIN_TEST(create1, "create a deep symbolic reference")
|
||||
must_pass(git_reference_resolve(&resolved_ref, looked_up_ref));
|
||||
must_be_true(git_oid_cmp(&id, git_reference_oid(resolved_ref)) == 0);
|
||||
|
||||
git_reference_delete(looked_up_ref);
|
||||
git_repository_free(repo);
|
||||
|
||||
must_pass(gitfo_unlink(ref_path)); /* TODO: replace with git_reference_delete() when available */
|
||||
END_TEST
|
||||
|
||||
BEGIN_TEST(create2, "create a new OID reference")
|
||||
@ -290,9 +293,28 @@ BEGIN_TEST(create2, "create a new OID reference")
|
||||
must_pass(git_reference_lookup(&looked_up_ref, repo, new_head));
|
||||
must_be_true(git_oid_cmp(&id, git_reference_oid(looked_up_ref)) == 0);
|
||||
|
||||
git_reference_delete(looked_up_ref);
|
||||
git_repository_free(repo);
|
||||
END_TEST
|
||||
|
||||
must_pass(gitfo_unlink(ref_path)); /* TODO: replace with git_reference_delete() when available */
|
||||
BEGIN_TEST(create3, "Can not create a new OID reference which targets at an unknown id")
|
||||
git_reference *new_reference, *looked_up_ref;
|
||||
git_repository *repo;
|
||||
git_oid id;
|
||||
|
||||
const char *new_head = "refs/heads/new-head";
|
||||
|
||||
git_oid_mkstr(&id, "deadbeef3f795b2b4353bcce3a527ad0a4f7f644");
|
||||
|
||||
must_pass(git_repository_open(&repo, REPOSITORY_FOLDER));
|
||||
|
||||
/* Create and write the new object id reference */
|
||||
must_fail(git_reference_create_oid(&new_reference, repo, new_head, &id));
|
||||
|
||||
/* Ensure the reference can't be looked-up... */
|
||||
must_fail(git_reference_lookup(&looked_up_ref, repo, new_head));
|
||||
|
||||
git_repository_free(repo);
|
||||
END_TEST
|
||||
|
||||
static const char *ref_name = "refs/heads/other";
|
||||
@ -892,6 +914,7 @@ BEGIN_SUITE(refs)
|
||||
ADD_TEST(create0);
|
||||
ADD_TEST(create1);
|
||||
ADD_TEST(create2);
|
||||
ADD_TEST(create3);
|
||||
|
||||
ADD_TEST(overwrite0);
|
||||
ADD_TEST(overwrite1);
|
||||
|
Loading…
Reference in New Issue
Block a user