diff options
author | Vicent Marti <tanoku@gmail.com> | 2011-06-28 19:15:48 +0200 |
---|---|---|
committer | Vicent Marti <tanoku@gmail.com> | 2011-06-28 19:36:27 +0200 |
commit | d5afc0390c3ef919fcde23300d7aefdaeafa5daa (patch) | |
tree | 0b661ef8536266c5bf5de645025c8072bc35dc85 /src | |
parent | 0b10c9ea6ef5d85d862edd044d96561c4fd16e9b (diff) | |
download | libgit2-d5afc0390c3ef919fcde23300d7aefdaeafa5daa.tar.gz |
Remove redundant methods from the API
A bunch of redundant methods have been removed from the external API.
- All the reference/tag creation methods with `_f` are gone. The force
flag is now passed as an argument to the normal create methods.
- All the different commit creation methods are gone; commit creation
now always requires a `git_commit` pointer for parents and a `git_tree`
pointer for tree, to ensure that corrupted commits cannot be generated.
- All the different tag creation methods are gone; tag creation now
always requires a `git_object` pointer to ensure that tags are not
created to inexisting objects.
Diffstat (limited to 'src')
-rw-r--r-- | src/commit.c | 90 | ||||
-rw-r--r-- | src/oid.c | 28 | ||||
-rw-r--r-- | src/refs.c | 238 | ||||
-rw-r--r-- | src/repository.c | 2 | ||||
-rw-r--r-- | src/tag.c | 180 |
5 files changed, 204 insertions, 334 deletions
diff --git a/src/commit.c b/src/commit.c index 6857eddab..c94ea7618 100644 --- a/src/commit.c +++ b/src/commit.c @@ -74,7 +74,6 @@ const git_oid *git_commit_id(git_commit *c) return git_object_id((git_object *)c); } - int git_commit_create_v( git_oid *oid, git_repository *repo, @@ -82,63 +81,31 @@ int git_commit_create_v( const git_signature *author, const git_signature *committer, const char *message, - const git_oid *tree_oid, - int parent_count, - ...) -{ - va_list ap; - int i, error; - const git_oid **oids; - - oids = git__malloc(parent_count * sizeof(git_oid *)); - - va_start(ap, parent_count); - for (i = 0; i < parent_count; ++i) - oids[i] = va_arg(ap, const git_oid *); - va_end(ap); - - error = git_commit_create( - oid, repo, update_ref, author, committer, message, - tree_oid, parent_count, oids); - - free((void *)oids); - - return error; -} - -int git_commit_create_ov( - git_oid *oid, - git_repository *repo, - const char *update_ref, - const git_signature *author, - const git_signature *committer, - const char *message, const git_tree *tree, int parent_count, ...) { va_list ap; int i, error; - const git_oid **oids; + const git_commit **parents; - oids = git__malloc(parent_count * sizeof(git_oid *)); + parents = git__malloc(parent_count * sizeof(git_commit *)); va_start(ap, parent_count); for (i = 0; i < parent_count; ++i) - oids[i] = git_object_id(va_arg(ap, const git_object *)); + parents[i] = va_arg(ap, const git_commit *); va_end(ap); error = git_commit_create( oid, repo, update_ref, author, committer, message, - git_object_id((git_object *)tree), - parent_count, oids); + tree, parent_count, parents); - free((void *)oids); + free((void *)parents); return error; } -int git_commit_create_o( +int git_commit_create( git_oid *oid, git_repository *repo, const char *update_ref, @@ -149,35 +116,6 @@ int git_commit_create_o( int parent_count, const git_commit *parents[]) { - int i, error; - const git_oid **oids; - - oids = git__malloc(parent_count * sizeof(git_oid *)); - - for (i = 0; i < parent_count; ++i) - oids[i] = git_object_id((git_object *)parents[i]); - - error = git_commit_create( - oid, repo, update_ref, author, committer, message, - git_object_id((git_object *)tree), - parent_count, oids); - - free((void *)oids); - - return error; -} - -int git_commit_create( - git_oid *oid, - git_repository *repo, - const char *update_ref, - const git_signature *author, - const git_signature *committer, - const char *message, - const git_oid *tree_oid, - int parent_count, - const git_oid *parents[]) -{ size_t final_size = 0; int message_length, author_length, committer_length; @@ -202,10 +140,17 @@ int git_commit_create( if ((error = git_odb_open_wstream(&stream, repo->db, final_size, GIT_OBJ_COMMIT)) < GIT_SUCCESS) return git__rethrow(error, "Failed to create commit"); - git__write_oid(stream, "tree", tree_oid); + if (git_object_owner((const git_object *)tree) != repo) + return git__throw(GIT_EINVALIDARGS, "The given tree does not belong to this repository"); - for (i = 0; i < parent_count; ++i) - git__write_oid(stream, "parent", parents[i]); + git__write_oid(stream, "tree", git_object_id((const git_object *)tree)); + + for (i = 0; i < parent_count; ++i) { + if (git_object_owner((const git_object *)parents[i]) != repo) + return git__throw(GIT_EINVALIDARGS, "The given parent does not belong to this repository"); + + git__write_oid(stream, "parent", git_object_id((const git_object *)parents[i])); + } stream->write(stream, author_str, author_length); free(author_str); @@ -213,7 +158,6 @@ int git_commit_create( stream->write(stream, committer_str, committer_length); free(committer_str); - stream->write(stream, "\n", 1); stream->write(stream, message, message_length); @@ -238,7 +182,7 @@ int git_commit_create( * point to) or after an orphan checkout, so if the target * branch doesn't exist yet, create it and return. */ - return git_reference_create_oid_f(&head, repo, git_reference_target(head), oid); + return git_reference_create_oid(&head, repo, git_reference_target(head), oid, 1); } error = git_reference_set_oid(head, oid); @@ -49,19 +49,37 @@ static signed char from_hex[] = { }; static char to_hex[] = "0123456789abcdef"; -int git_oid_fromstr(git_oid *out, const char *str) +int git_oid_fromstrn(git_oid *out, const char *str, size_t length) { size_t p; - for (p = 0; p < sizeof(out->id); p++, str += 2) { - int v = (from_hex[(unsigned char)str[0]] << 4) - | from_hex[(unsigned char)str[1]]; + + if (length > GIT_OID_HEXSZ) + length = GIT_OID_HEXSZ; + + if (length % 2) + length--; + + for (p = 0; p < length; p += 2) { + int v = (from_hex[(unsigned char)str[p + 0]] << 4) + | from_hex[(unsigned char)str[p + 1]]; + if (v < 0) return git__throw(GIT_ENOTOID, "Failed to generate sha1. Given string is not a valid sha1 hash"); - out->id[p] = (unsigned char)v; + + out->id[p / 2] = (unsigned char)v; } + + for (; p < GIT_OID_HEXSZ; p += 2) + out->id[p / 2] = 0x0; + return GIT_SUCCESS; } +int git_oid_fromstr(git_oid *out, const char *str) +{ + return git_oid_fromstrn(out, str, GIT_OID_HEXSZ); +} + GIT_INLINE(char) *fmt_one(char *str, unsigned int val) { *str++ = to_hex[val >> 4]; diff --git a/src/refs.c b/src/refs.c index ac13736eb..d4a820b9b 100644 --- a/src/refs.c +++ b/src/refs.c @@ -920,117 +920,6 @@ cleanup: return error == GIT_SUCCESS ? GIT_SUCCESS : git__rethrow(error, "Failed to write packed reference"); } -/***************************************** - * Internal methods - reference creation - *****************************************/ - -static int reference_create_symbolic(git_reference **ref_out, git_repository *repo, const char *name, const char *target, int force) -{ - char normalized[GIT_REFNAME_MAX]; - int error = GIT_SUCCESS, updated = 0; - git_reference *ref = NULL, *old_ref = NULL; - - if (git_reference_lookup(&ref, repo, name) == GIT_SUCCESS && !force) - return git__throw(GIT_EEXISTS, "Failed to create symbolic reference. Reference already exists"); - - /* - * If they old ref was of the same type, then we can just update - * it (once we've checked that the target is valid). Otherwise we - * need a new reference because we can't make a symbolic ref out - * of an oid one. - * If if didn't exist, then we need to create a new one anyway. - */ - if (ref && ref->type & GIT_REF_SYMBOLIC){ - updated = 1; - } else { - ref = NULL; - error = reference_create(&ref, repo, name, GIT_REF_SYMBOLIC); - if (error < GIT_SUCCESS) - goto cleanup; - } - - /* The target can aither be the name of an object id reference or the name of another symbolic reference */ - error = normalize_name(normalized, sizeof(normalized), target, 0); - if (error < GIT_SUCCESS) - goto cleanup; - - /* set the target; this will write the reference on disk */ - error = git_reference_set_target(ref, normalized); - if (error < GIT_SUCCESS) - goto cleanup; - - /* - * If we didn't update the ref, then we need to insert or replace - * it in the loose cache. If we replaced a ref, free it. - */ - if (!updated){ - error = git_hashtable_insert2(repo->references.loose_cache, ref->name, ref, (void **) &old_ref); - if (error < GIT_SUCCESS) - goto cleanup; - - if(old_ref) - reference_free(old_ref); - } - - *ref_out = ref; - - return error == GIT_SUCCESS ? GIT_SUCCESS : git__rethrow(error, "Failed to create symbolic reference"); - -cleanup: - reference_free(ref); - return error == GIT_SUCCESS ? GIT_SUCCESS : git__rethrow(error, "Failed to create symbolic reference"); -} - -static int reference_create_oid(git_reference **ref_out, git_repository *repo, const char *name, const git_oid *id, int force) -{ - int error = GIT_SUCCESS, updated = 0; - git_reference *ref = NULL, *old_ref = NULL; - - if(git_reference_lookup(&ref, repo, name) == GIT_SUCCESS && !force) - return git__throw(GIT_EEXISTS, "Failed to create reference OID. Reference already exists"); - - if ((error = reference_available(repo, name, NULL)) < GIT_SUCCESS) - return git__rethrow(error, "Failed to create reference"); - - /* - * If they old ref was of the same type, then we can just update - * it (once we've checked that the target is valid). Otherwise we - * need a new reference because we can't make a symbolic ref out - * of an oid one. - * If if didn't exist, then we need to create a new one anyway. - */ - if (ref && ref-> type & GIT_REF_OID){ - updated = 1; - } else { - ref = NULL; - error = reference_create(&ref, repo, name, GIT_REF_OID); - if (error < GIT_SUCCESS) - goto cleanup; - } - - /* set the oid; this will write the reference on disk */ - error = git_reference_set_oid(ref, id); - if (error < GIT_SUCCESS) - goto cleanup; - - if(!updated){ - error = git_hashtable_insert2(repo->references.loose_cache, ref->name, ref, (void **) &old_ref); - if (error < GIT_SUCCESS) - goto cleanup; - - if(old_ref) - reference_free(old_ref); - } - - *ref_out = ref; - - return error == GIT_SUCCESS ? GIT_SUCCESS : git__rethrow(error, "Failed to create reference OID"); - -cleanup: - reference_free(ref); - return error == GIT_SUCCESS ? GIT_SUCCESS : git__rethrow(error, "Failed to create reference OID"); -} - static int _reference_available_cb(const char *ref, void *data) { const char *new, *old; @@ -1261,26 +1150,6 @@ int git_reference_lookup(git_reference **ref_out, git_repository *repo, const ch return git__throw(GIT_ENOTFOUND, "Failed to lookup reference. Reference doesn't exist"); } -int git_reference_create_symbolic(git_reference **ref_out, git_repository *repo, const char *name, const char *target) -{ - return reference_create_symbolic(ref_out, repo, name, target, 0); -} - -int git_reference_create_symbolic_f(git_reference **ref_out, git_repository *repo, const char *name, const char *target) -{ - return reference_create_symbolic(ref_out, repo, name, target, 1); -} - -int git_reference_create_oid(git_reference **ref_out, git_repository *repo, const char *name, const git_oid *id) -{ - return reference_create_oid(ref_out, repo, name, id, 0); -} - -int git_reference_create_oid_f(git_reference **ref_out, git_repository *repo, const char *name, const git_oid *id) -{ - return reference_create_oid(ref_out, repo, name, id, 1); -} - /** * Getters */ @@ -1335,6 +1204,113 @@ const char *git_reference_target(git_reference *ref) return ((reference_symbolic *)ref)->target; } +int git_reference_create_symbolic(git_reference **ref_out, git_repository *repo, const char *name, const char *target, int force) +{ + char normalized[GIT_REFNAME_MAX]; + int error = GIT_SUCCESS, updated = 0; + git_reference *ref = NULL, *old_ref = NULL; + + if (git_reference_lookup(&ref, repo, name) == GIT_SUCCESS && !force) + return git__throw(GIT_EEXISTS, "Failed to create symbolic reference. Reference already exists"); + + /* + * If they old ref was of the same type, then we can just update + * it (once we've checked that the target is valid). Otherwise we + * need a new reference because we can't make a symbolic ref out + * of an oid one. + * If if didn't exist, then we need to create a new one anyway. + */ + if (ref && ref->type & GIT_REF_SYMBOLIC){ + updated = 1; + } else { + ref = NULL; + error = reference_create(&ref, repo, name, GIT_REF_SYMBOLIC); + if (error < GIT_SUCCESS) + goto cleanup; + } + + /* The target can aither be the name of an object id reference or the name of another symbolic reference */ + error = normalize_name(normalized, sizeof(normalized), target, 0); + if (error < GIT_SUCCESS) + goto cleanup; + + /* set the target; this will write the reference on disk */ + error = git_reference_set_target(ref, normalized); + if (error < GIT_SUCCESS) + goto cleanup; + + /* + * If we didn't update the ref, then we need to insert or replace + * it in the loose cache. If we replaced a ref, free it. + */ + if (!updated){ + error = git_hashtable_insert2(repo->references.loose_cache, ref->name, ref, (void **) &old_ref); + if (error < GIT_SUCCESS) + goto cleanup; + + if(old_ref) + reference_free(old_ref); + } + + *ref_out = ref; + + return error == GIT_SUCCESS ? GIT_SUCCESS : git__rethrow(error, "Failed to create symbolic reference"); + +cleanup: + reference_free(ref); + return error == GIT_SUCCESS ? GIT_SUCCESS : git__rethrow(error, "Failed to create symbolic reference"); +} + +int git_reference_create_oid(git_reference **ref_out, git_repository *repo, const char *name, const git_oid *id, int force) +{ + int error = GIT_SUCCESS, updated = 0; + git_reference *ref = NULL, *old_ref = NULL; + + if(git_reference_lookup(&ref, repo, name) == GIT_SUCCESS && !force) + return git__throw(GIT_EEXISTS, "Failed to create reference OID. Reference already exists"); + + if ((error = reference_available(repo, name, NULL)) < GIT_SUCCESS) + return git__rethrow(error, "Failed to create reference"); + + /* + * If they old ref was of the same type, then we can just update + * it (once we've checked that the target is valid). Otherwise we + * need a new reference because we can't make a symbolic ref out + * of an oid one. + * If if didn't exist, then we need to create a new one anyway. + */ + if (ref && ref-> type & GIT_REF_OID){ + updated = 1; + } else { + ref = NULL; + error = reference_create(&ref, repo, name, GIT_REF_OID); + if (error < GIT_SUCCESS) + goto cleanup; + } + + /* set the oid; this will write the reference on disk */ + error = git_reference_set_oid(ref, id); + if (error < GIT_SUCCESS) + goto cleanup; + + if(!updated){ + error = git_hashtable_insert2(repo->references.loose_cache, ref->name, ref, (void **) &old_ref); + if (error < GIT_SUCCESS) + goto cleanup; + + if(old_ref) + reference_free(old_ref); + } + + *ref_out = ref; + + return error == GIT_SUCCESS ? GIT_SUCCESS : git__rethrow(error, "Failed to create reference OID"); + +cleanup: + reference_free(ref); + return error == GIT_SUCCESS ? GIT_SUCCESS : git__rethrow(error, "Failed to create reference OID"); +} + /** * Setters */ diff --git a/src/repository.c b/src/repository.c index 1fef73907..7e3f26e1b 100644 --- a/src/repository.c +++ b/src/repository.c @@ -626,7 +626,7 @@ static int repo_init_reinit(repo_init *results) static int repo_init_createhead(git_repository *repo) { git_reference *head_reference; - return git_reference_create_symbolic(&head_reference, repo, GIT_HEAD_FILE, GIT_REFS_HEADS_MASTER_FILE); /* TODO: finalize moving refs.c to new error handling */ + return git_reference_create_symbolic(&head_reference, repo, GIT_HEAD_FILE, GIT_REFS_HEADS_MASTER_FILE, 0); } static int repo_init_check_head_existence(char * repository_path) @@ -180,52 +180,11 @@ static int retreive_tag_reference(git_reference **tag_reference_out, char *ref_n return GIT_SUCCESS; } -/* tag_reference_out will contain the reference of the tag if exists, otherwise NULL */ -static int tag_valid_in_odb( - git_reference **tag_reference_out, - char *ref_name_out, - const git_oid *target, - git_otype target_type, - git_repository *repo, - const char *tag_name) { - - int error; - - *tag_reference_out = NULL; - - - error = retreive_tag_reference(tag_reference_out, ref_name_out, repo, tag_name); - - switch (error) { - case GIT_SUCCESS: - /* Fall trough */ - case GIT_ENOTFOUND: - break; - - default: - return git__rethrow(error, "Failed to create tag"); - } - - if (!git_odb_exists(repo->db, target)) - return git__throw(GIT_ENOTFOUND, "Failed to create tag. Object to tag doesn't exist"); - - /* Try to find out what the type is */ - if (target_type == GIT_OBJ_ANY) { - size_t _unused; - error = git_odb_read_header(&_unused, &target_type, repo->db, target); - if (error < GIT_SUCCESS) - return git__rethrow(error, "Failed to create tag"); - } - - return GIT_SUCCESS; -} - -static int tag_create( +int git_tag_create( git_oid *oid, git_repository *repo, const char *tag_name, - const git_oid *target, - git_otype target_type, + const git_object *target, const git_signature *tagger, const char *message, int allow_ref_overwrite) @@ -235,20 +194,31 @@ static int tag_create( const char *type_str; char *tagger_str; - git_reference *new_ref; + git_reference *new_ref = NULL; char ref_name[GIT_REFNAME_MAX]; int type_str_len, tag_name_len, tagger_str_len, message_len; int error, should_update_ref = 0; - if ((error = tag_valid_in_odb(&new_ref, ref_name, target, target_type, repo, tag_name)) < GIT_SUCCESS) - return git__rethrow(error, "Failed to create tag"); + if (git_object_owner(target) != repo) + return git__throw(GIT_EINVALIDARGS, "The given target does not belong to this repository"); + + error = retreive_tag_reference(&new_ref, ref_name, repo, tag_name); + switch (error) { + case GIT_SUCCESS: + case GIT_ENOTFOUND: + break; + + default: + return git__rethrow(error, "Failed to create tag"); + } + /** Ensure the tag name doesn't conflict with an already existing * reference unless overwriting has explictly been requested **/ - if(new_ref != NULL) { - if(!allow_ref_overwrite) { + if (new_ref != NULL) { + if (!allow_ref_overwrite) { git_oid_cpy(oid, git_reference_oid(new_ref)); return git__throw(GIT_EEXISTS, "Tag already exists"); } else { @@ -256,8 +226,7 @@ static int tag_create( } } - type_str = git_object_type2string(target_type); - + type_str = git_object_type2string(git_object_type(target)); tagger_str_len = git_signature__write(&tagger_str, "tagger", tagger); type_str_len = strlen(type_str); @@ -273,7 +242,7 @@ static int tag_create( if ((error = git_odb_open_wstream(&stream, repo->db, final_size, GIT_OBJ_TAG)) < GIT_SUCCESS) return git__rethrow(error, "Failed to create tag"); - git__write_oid(stream, "object", target); + git__write_oid(stream, "object", git_object_id(target)); stream->write(stream, "type ", STRLEN("type ")); stream->write(stream, type_str, type_str_len); @@ -296,18 +265,19 @@ static int tag_create( return git__rethrow(error, "Failed to create tag"); if (!should_update_ref) - error = git_reference_create_oid(&new_ref, repo, ref_name, oid); + error = git_reference_create_oid(&new_ref, repo, ref_name, oid, 0); else error = git_reference_set_oid(new_ref, oid); return error == GIT_SUCCESS ? GIT_SUCCESS : git__rethrow(error, "Failed to create tag"); } -int git_tag_create_frombuffer(git_oid *oid, git_repository *repo, const char *buffer) +int git_tag_create_frombuffer(git_oid *oid, git_repository *repo, const char *buffer, int allow_ref_overwrite) { git_tag tag; - int error; + int error, should_update_ref = 0; git_odb_stream *stream; + git_odb_object *target_obj; git_reference *new_ref; char ref_name[GIT_REFNAME_MAX]; @@ -317,16 +287,38 @@ int git_tag_create_frombuffer(git_oid *oid, git_repository *repo, const char *bu memset(&tag, 0, sizeof(tag)); /* validate the buffer */ - if ((error = parse_tag_buffer(&tag, buffer, buffer + strlen(buffer))) < GIT_SUCCESS) return git__rethrow(error, "Failed to create tag"); - - if ((error = tag_valid_in_odb(&new_ref, ref_name, &tag.target, tag.type, repo, tag.tag_name)) < GIT_SUCCESS) + + /* validate the target */ + if ((error = git_odb_read(&target_obj, repo->db, &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); + error = retreive_tag_reference(&new_ref, ref_name, repo, tag.tag_name); + + switch (error) { + case GIT_SUCCESS: + case GIT_ENOTFOUND: + break; + + default: + return git__rethrow(error, "Failed to create tag"); + } + + /** Ensure the tag name doesn't conflict with an already existing + * reference unless overwriting has explictly been requested **/ if (new_ref != NULL) { - git_oid_cpy(oid, git_reference_oid(new_ref)); - return git__throw(GIT_EEXISTS, "Tag already exists"); + if (!allow_ref_overwrite) { + git_oid_cpy(oid, git_reference_oid(new_ref)); + return git__throw(GIT_EEXISTS, "Tag already exists"); + } else { + should_update_ref = 1; + } } /* write the buffer */ @@ -340,9 +332,11 @@ int git_tag_create_frombuffer(git_oid *oid, git_repository *repo, const char *bu if (error < GIT_SUCCESS) return git__rethrow(error, "Failed to create tag"); - - - error = git_reference_create_oid(&new_ref, repo, ref_name, oid); + + if (!should_update_ref) + error = git_reference_create_oid(&new_ref, repo, ref_name, oid, 0); + else + error = git_reference_set_oid(new_ref, oid); git_signature_free(tag.tagger); free(tag.tag_name); @@ -351,68 +345,6 @@ int git_tag_create_frombuffer(git_oid *oid, git_repository *repo, const char *bu return error == GIT_SUCCESS ? GIT_SUCCESS : git__rethrow(error, "Failed to create tag"); } -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; |