diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/commit.c | 183 | ||||
| -rw-r--r-- | src/config_file.c | 1 | ||||
| -rw-r--r-- | src/odb_loose.c | 2 | ||||
| -rw-r--r-- | src/oid.c | 6 | ||||
| -rw-r--r-- | src/repository.c | 9 | ||||
| -rw-r--r-- | src/status.c | 2 | ||||
| -rw-r--r-- | src/submodule.c | 3 |
7 files changed, 119 insertions, 87 deletions
diff --git a/src/commit.c b/src/commit.c index 2e359929b..9bc9d9443 100644 --- a/src/commit.c +++ b/src/commit.c @@ -69,24 +69,88 @@ int git_commit_create_v( ...) { va_list ap; - int i, error; + int i, res; const git_commit **parents; parents = git__malloc(parent_count * sizeof(git_commit *)); + GITERR_CHECK_ALLOC(parents); va_start(ap, parent_count); for (i = 0; i < parent_count; ++i) parents[i] = va_arg(ap, const git_commit *); va_end(ap); - error = git_commit_create( + res = git_commit_create( oid, repo, update_ref, author, committer, message_encoding, message, tree, parent_count, parents); git__free((void *)parents); + return res; +} + +/* Update the reference named `ref_name` so it points to `oid` */ +static int update_reference(git_repository *repo, git_oid *oid, const char *ref_name) +{ + git_reference *ref; + int res; + + res = git_reference_lookup(&ref, repo, update_ref); + + /* If we haven't found the reference at all, we assume we need to create + * a new reference and that's it */ + if (res == GIT_ENOTFOUND) { + giterr_clear(); + return git_reference_create_oid(NULL, repo, update_ref, oid, 1); + } + + if (res < 0) + return -1; + + /* If we have found a reference, but it's symbolic, we need to update + * the direct reference it points to */ + if (git_reference_type(ref) == GIT_REF_SYMBOLIC) { + git_reference *aux; + const char *sym_target; + + /* The target pointed at by this reference */ + sym_target = git_reference_target(ref); + + /* resolve the reference to the target it points to */ + res = git_reference_resolve(&aux, ref); - return error; + /* + * if the symbolic reference pointed to an inexisting ref, + * this is means we're creating a new branch, for example. + * We need to create a new direct reference with that name + */ + if (res == GIT_ENOTFOUND) { + giterr_clear(); + res = git_reference_create_oid(NULL, repo, sym_target, oid, 1); + git_reference_free(ref); + return res; + } + + /* free the original symbolic reference now; not before because + * we're using the `sym_target` pointer */ + git_reference_free(ref); + + if (res < 0) + return -1; + + /* store the newly found direct reference in its place */ + ref = aux; + } + + /* ref is made to point to `oid`: ref is either the original reference, + * or the target of the symbolic reference we've looked up */ + res = git_reference_set_oid(ref, oid); + git_reference_free(ref); + return res; + +on_error: + git_reference_free(ref); + return -1; } int git_commit_create( @@ -102,20 +166,15 @@ int git_commit_create( const git_commit *parents[]) { git_buf commit = GIT_BUF_INIT; - int error, i; + int 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"); + assert(git_object_owner((const git_object *)tree) == repo) git_oid__writebuf(&commit, "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) { - error = git__throw(GIT_EINVALIDARGS, "The given parent does not belong to this repository"); - goto cleanup; - } - + assert(git_object_owner((const git_object *)parents[i]) == repo); git_oid__writebuf(&commit, "parent ", git_object_id((const git_object *)parents[i])); } @@ -128,67 +187,25 @@ int git_commit_create( git_buf_putc(&commit, '\n'); git_buf_puts(&commit, message); - if (git_buf_oom(&commit)) { - error = git__throw(GIT_ENOMEM, - "Not enough memory to build the commit data"); - goto cleanup; - } - - 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) { - git_reference *head; - git_reference *target; - - error = git_reference_lookup(&head, repo, update_ref); - if (error < GIT_SUCCESS && error != GIT_ENOTFOUND) - return git__rethrow(error, "Failed to create commit"); - - if (error != GIT_ENOTFOUND) { - update_ref = git_reference_target(head); - error = git_reference_resolve(&target, head); - } - - if (error < GIT_SUCCESS) { - if (error != GIT_ENOTFOUND) { - git_reference_free(head); - return git__rethrow(error, "Failed to create commit"); - } - /* - * The target of the reference was not found. This can happen - * just after a repository has been initialized (the master - * branch doesn't exist yet, as it doesn't have anything to - * point to) or after an orphan checkout, so if the target - * branch doesn't exist yet, create it and return. - */ - error = git_reference_create_oid(&target, repo, update_ref, oid, 1); + if (git_buf_oom(&commit)) + goto on_error; - git_reference_free(head); - if (error == GIT_SUCCESS) - git_reference_free(target); + if (git_repository_odb__weakptr(&odb, repo) < 0) + goto on_error; - return error; - } + if (git_odb_write(oid, odb, commit.ptr, commit.size, GIT_OBJ_COMMIT) < 0) + goto on_error; - error = git_reference_set_oid(target, oid); - - git_reference_free(head); - git_reference_free(target); - } + git_buf_free(&commit); - if (error < GIT_SUCCESS) - return git__rethrow(error, "Failed to create commit"); + if (update_ref != NULL) + return update_reference(repo, oid, update_ref); - return GIT_SUCCESS; + return 0; -cleanup: +on_error: git_buf_free(&commit); - return error; + return -1; } int git_commit__parse_buffer(git_commit *commit, const void *data, size_t len) @@ -201,31 +218,37 @@ int git_commit__parse_buffer(git_commit *commit, const void *data, size_t len) git_vector_init(&commit->parent_oids, 4, NULL); - if ((error = git_oid__parse(&commit->tree_oid, &buffer, buffer_end, "tree ")) < GIT_SUCCESS) - return git__rethrow(error, "Failed to parse buffer"); + if (git_oid__parse(&commit->tree_oid, &buffer, buffer_end, "tree ")) < 0) + goto bad_buffer; /* * TODO: commit grafts! */ - while (git_oid__parse(&parent_oid, &buffer, buffer_end, "parent ") == GIT_SUCCESS) { + while (git_oid__parse(&parent_oid, &buffer, buffer_end, "parent ") == 0) { git_oid *new_oid; new_oid = git__malloc(sizeof(git_oid)); + GITERR_CHECK_ALLOC(new_oid); + git_oid_cpy(new_oid, &parent_oid); - if (git_vector_insert(&commit->parent_oids, new_oid) < GIT_SUCCESS) - return GIT_ENOMEM; + if (git_vector_insert(&commit->parent_oids, new_oid) < 0) + return -1; } commit->author = git__malloc(sizeof(git_signature)); - if ((error = git_signature__parse(commit->author, &buffer, buffer_end, "author ", '\n')) < GIT_SUCCESS) - return git__rethrow(error, "Failed to parse commit"); + GITERR_CHECK_ALLOC(commit->author); + + if (git_signature__parse(commit->author, &buffer, buffer_end, "author ", '\n') < 0) + return -1; /* Always parse the committer; we need the commit time */ commit->committer = git__malloc(sizeof(git_signature)); - if ((error = git_signature__parse(commit->committer, &buffer, buffer_end, "committer ", '\n')) < GIT_SUCCESS) - return git__rethrow(error, "Failed to parse commit"); + GITERR_CHECK_ALLOC(commit->committer); + + if (git_signature__parse(commit->committer, &buffer, buffer_end, "committer ", '\n') < 0) + return -1; if (git__prefixcmp(buffer, "encoding ") == 0) { const char *encoding_end; @@ -236,8 +259,7 @@ int git_commit__parse_buffer(git_commit *commit, const void *data, size_t len) encoding_end++; commit->message_encoding = git__strndup(buffer, encoding_end - buffer); - if (!commit->message_encoding) - return GIT_ENOMEM; + GITERR_CHECK_ALLOC(commit->message_encoding); buffer = encoding_end; } @@ -248,11 +270,14 @@ int git_commit__parse_buffer(git_commit *commit, const void *data, size_t len) if (buffer <= buffer_end) { commit->message = git__strndup(buffer, buffer_end - buffer); - if (!commit->message) - return GIT_ENOMEM; + GITERR_CHECK_ALLOC(commit->message); } - return GIT_SUCCESS; + return 0; + +bad_buffer: + giterr_set(GITERR_OBJECT, "Failed to parse bad commit object"); + return -1; } int git_commit__parse(git_commit *commit, git_odb_object *obj) diff --git a/src/config_file.c b/src/config_file.c index 60d4c567e..e16606512 100644 --- a/src/config_file.c +++ b/src/config_file.c @@ -334,6 +334,7 @@ static int config_get_multivar( var = var->next; } while (var != NULL); + regfree(®ex); } else { /* no regex; go through all the variables */ do { diff --git a/src/odb_loose.c b/src/odb_loose.c index 085df428a..b593d1846 100644 --- a/src/odb_loose.c +++ b/src/odb_loose.c @@ -772,7 +772,7 @@ static int loose_backend__stream(git_odb_stream **stream_out, git_odb_backend *_ static int loose_backend__write(git_oid *oid, git_odb_backend *_backend, const void *data, size_t len, git_otype type) { - int error, header_len; + int error = 0, header_len; git_buf final_path = GIT_BUF_INIT; char header[64]; git_filebuf fbuf = GIT_FILEBUF_INIT; @@ -125,13 +125,13 @@ int git_oid__parse( const char *buffer = *buffer_out; if (buffer + (header_len + sha_len + 1) > buffer_end) - return oid_error_invalid("input is too short"); + return -1; if (memcmp(buffer, header, header_len) != 0) - return oid_error_invalid("did not match expected header"); + return -1; if (buffer[header_len + sha_len] != '\n') - return oid_error_invalid("not terminated correctly"); + return -1; if (git_oid_fromstr(oid, buffer + header_len) < 0) return -1; diff --git a/src/repository.c b/src/repository.c index 4e0f9d491..ce313280e 100644 --- a/src/repository.c +++ b/src/repository.c @@ -871,13 +871,16 @@ const char *git_repository_workdir(git_repository *repo) int git_repository_set_workdir(git_repository *repo, const char *workdir) { + git_buf path = GIT_BUF_INIT; + assert(repo && workdir); - free(repo->workdir); + if (git_path_prettify_dir(&path, workdir, NULL) < 0) + return -1; - repo->workdir = git__strdup(workdir); - GITERR_CHECK_ALLOC(repo->workdir); + free(repo->workdir); + repo->workdir = git_buf_detach(&path); repo->is_bare = 0; return 0; } diff --git a/src/status.c b/src/status.c index 88dd5e03b..7cd914f21 100644 --- a/src/status.c +++ b/src/status.c @@ -43,6 +43,8 @@ static int resolve_head_to_tree(git_tree **tree, git_repository *repo) if (git_object_lookup(&obj, repo, git_reference_oid(head), GIT_OBJ_ANY) < 0) goto fail; + git_reference_free(head); + switch (git_object_type(obj)) { case GIT_OBJ_TREE: *tree = (git_tree *)obj; diff --git a/src/submodule.c b/src/submodule.c index be99b86d5..907e43e88 100644 --- a/src/submodule.c +++ b/src/submodule.c @@ -182,6 +182,7 @@ static int submodule_from_config( goto fail; sm->refcount++; } + git_buf_free(&name); if (old_sm && ((git_submodule *)old_sm) != sm) { /* TODO: log entry about multiple submodules with same path */ @@ -255,7 +256,7 @@ static int load_submodule_config(git_repository *repo) GITERR_CHECK_ALLOC(smcfg); /* scan index for gitmodules (and .gitmodules entry) */ - if ((error = git_repository_index(&index, repo)) < 0) + if ((error = git_repository_index__weakptr(&index, repo)) < 0) goto cleanup; memset(&gitmodules_oid, 0, sizeof(gitmodules_oid)); max_i = git_index_entrycount(index); |
