Skip to content

Commit

Permalink
Merge remote-tracking branch 'libgit2/development' into bs/more-reflo…
Browse files Browse the repository at this point in the history
…g-stuff
  • Loading branch information
ben committed Feb 5, 2014
2 parents 010cec3 + 629ba7f commit 0de2c4e
Show file tree
Hide file tree
Showing 11 changed files with 548 additions and 96 deletions.
18 changes: 12 additions & 6 deletions include/git2/revwalk.h
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ GIT_EXTERN(void) git_revwalk_reset(git_revwalk *walker);
/**
* Mark a commit to start traversal from.
*
* The given OID must belong to a commit on the walked
* The given OID must belong to a committish on the walked
* repository.
*
* The given commit will be used as one of the roots
Expand All @@ -108,7 +108,10 @@ GIT_EXTERN(int) git_revwalk_push(git_revwalk *walk, const git_oid *id);
* pattern will be pushed to the revision walker.
*
* A leading 'refs/' is implied if not present as well as a trailing
* '/ *' if the glob lacks '?', '*' or '['.
* '/\*' if the glob lacks '?', '\*' or '['.
*
* Any references matching this glob which do not point to a
* committish will be ignored.
*
* @param walk the walker being used for the traversal
* @param glob the glob pattern references should match
Expand All @@ -127,7 +130,7 @@ GIT_EXTERN(int) git_revwalk_push_head(git_revwalk *walk);
/**
* Mark a commit (and its ancestors) uninteresting for the output.
*
* The given OID must belong to a commit on the walked
* The given OID must belong to a committish on the walked
* repository.
*
* The resolved commit and all its parents will be hidden from the
Expand All @@ -147,7 +150,10 @@ GIT_EXTERN(int) git_revwalk_hide(git_revwalk *walk, const git_oid *commit_id);
* revision walk.
*
* A leading 'refs/' is implied if not present as well as a trailing
* '/ *' if the glob lacks '?', '*' or '['.
* '/\*' if the glob lacks '?', '\*' or '['.
*
* Any references matching this glob which do not point to a
* committish will be ignored.
*
* @param walk the walker being used for the traversal
* @param glob the glob pattern references should match
Expand All @@ -166,7 +172,7 @@ GIT_EXTERN(int) git_revwalk_hide_head(git_revwalk *walk);
/**
* Push the OID pointed to by a reference
*
* The reference must point to a commit.
* The reference must point to a committish.
*
* @param walk the walker being used for the traversal
* @param refname the reference to push
Expand All @@ -177,7 +183,7 @@ GIT_EXTERN(int) git_revwalk_push_ref(git_revwalk *walk, const char *refname);
/**
* Hide the OID pointed to by a reference
*
* The reference must point to a commit.
* The reference must point to a committish.
*
* @param walk the walker being used for the traversal
* @param refname the reference to hide
Expand Down
40 changes: 12 additions & 28 deletions src/commit.c
Original file line number Diff line number Diff line change
Expand Up @@ -183,33 +183,15 @@ int git_commit__parse(void *_commit, git_odb_object *odb_obj)
const char *buffer_start = git_odb_object_data(odb_obj), *buffer;
const char *buffer_end = buffer_start + git_odb_object_size(odb_obj);
git_oid parent_id;
uint32_t parent_count = 0;
size_t header_len;

/* find end-of-header (counting parents as we go) */
for (buffer = buffer_start; buffer < buffer_end; ++buffer) {
if (!strncmp("\n\n", buffer, 2)) {
++buffer;
break;
}
if (!strncmp("\nparent ", buffer, strlen("\nparent ")))
++parent_count;
}

header_len = buffer - buffer_start;
commit->raw_header = git__strndup(buffer_start, header_len);
GITERR_CHECK_ALLOC(commit->raw_header);
buffer = buffer_start;

/* point "buffer" to header data */
buffer = commit->raw_header;
buffer_end = commit->raw_header + header_len;

if (parent_count < 1)
parent_count = 1;

git_array_init_to_size(commit->parent_ids, parent_count);
/* Allocate for one, which will allow not to realloc 90% of the time */
git_array_init_to_size(commit->parent_ids, 1);
GITERR_CHECK_ARRAY(commit->parent_ids);

/* The tree is always the first field */
if (git_oid__parse(&commit->tree_id, &buffer, buffer_end, "tree ") < 0)
goto bad_buffer;

Expand Down Expand Up @@ -240,6 +222,9 @@ int git_commit__parse(void *_commit, git_odb_object *odb_obj)
/* Parse add'l header entries */
while (buffer < buffer_end) {
const char *eoln = buffer;
if (buffer[-1] == '\n' && buffer[0] == '\n')
break;

while (eoln < buffer_end && *eoln != '\n')
++eoln;

Expand All @@ -255,13 +240,12 @@ int git_commit__parse(void *_commit, git_odb_object *odb_obj)
buffer = eoln;
}

/* point "buffer" to data after header */
buffer = git_odb_object_data(odb_obj);
buffer_end = buffer + git_odb_object_size(odb_obj);
header_len = buffer - buffer_start;
commit->raw_header = git__strndup(buffer_start, header_len);
GITERR_CHECK_ALLOC(commit->raw_header);

buffer += header_len;
if (*buffer == '\n')
++buffer;
/* point "buffer" to data after header, +1 for the final LF */
buffer = buffer_start + header_len + 1;

/* extract commit message */
if (buffer <= buffer_end) {
Expand Down
11 changes: 4 additions & 7 deletions src/merge.c
Original file line number Diff line number Diff line change
Expand Up @@ -2330,7 +2330,7 @@ static int merge_check_index(size_t *conflicts, git_repository *repo, git_index

static int merge_check_workdir(size_t *conflicts, git_repository *repo, git_index *index_new, git_vector *merged_paths)
{
git_tree *head_tree = NULL;
git_index *index_repo = NULL;
git_diff *wd_diff_list = NULL;
git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
int error = 0;
Expand All @@ -2341,23 +2341,20 @@ static int merge_check_workdir(size_t *conflicts, git_repository *repo, git_inde

opts.flags |= GIT_DIFF_INCLUDE_UNTRACKED;

if ((error = git_repository_head_tree(&head_tree, repo)) < 0)
goto done;

/* Workdir changes may exist iff they do not conflict with changes that
* will be applied by the merge (including conflicts). Ensure that there
* are no changes in the workdir to these paths.
*/
opts.pathspec.count = merged_paths->length;
opts.pathspec.strings = (char **)merged_paths->contents;

if ((error = git_diff_tree_to_workdir(&wd_diff_list, repo, head_tree, &opts)) < 0)
if ((error = git_diff_index_to_workdir(&wd_diff_list, repo, index_repo, &opts)) < 0)
goto done;

*conflicts = wd_diff_list->deltas.length;

done:
git_tree_free(head_tree);
git_index_free(index_repo);
git_diff_free(wd_diff_list);

return error;
Expand Down Expand Up @@ -2400,7 +2397,7 @@ int git_merge__indexes(git_repository *repo, git_index *index_new)

/* Remove removed items from the index */
git_vector_foreach(&paths, i, path) {
if ((e = git_index_get_bypath(index_new, path, 0)) == NULL) {
if (git_index_get_bypath(index_new, path, 0) == NULL) {
if ((error = git_index_remove(index_repo, path, 0)) < 0 &&
error != GIT_ENOTFOUND)
goto done;
Expand Down
13 changes: 1 addition & 12 deletions src/posix.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,18 +89,7 @@ extern struct tm * p_gmtime_r (const time_t *timer, struct tm *result);
# include "unix/posix.h"
#endif

#if defined(__MINGW32__) || defined(__sun) || defined(__APPLE__)
# define NO_STRNLEN
#endif

#ifdef NO_STRNLEN
GIT_INLINE(size_t) p_strnlen(const char *s, size_t maxlen) {
const char *end = memchr(s, 0, maxlen);
return end ? (size_t)(end - s) : maxlen;
}
#else
# define p_strnlen strnlen
#endif
#include "strnlen.h"

#ifdef NO_READDIR_R
# include <dirent.h>
Expand Down
3 changes: 1 addition & 2 deletions src/revparse.c
Original file line number Diff line number Diff line change
Expand Up @@ -490,8 +490,7 @@ static int handle_grep_syntax(git_object **out, git_repository *repo, const git_
git_revwalk_sorting(walk, GIT_SORT_TIME);

if (spec_oid == NULL) {
// TODO: @carlosmn: The glob should be refs/* but this makes git_revwalk_next() fails
if ((error = git_revwalk_push_glob(walk, GIT_REFS_HEADS_DIR "*")) < 0)
if ((error = git_revwalk_push_glob(walk, "refs/*")) < 0)
goto cleanup;
} else if ((error = git_revwalk_push(walk, spec_oid)) < 0)
goto cleanup;
Expand Down
72 changes: 42 additions & 30 deletions src/revwalk.c
Original file line number Diff line number Diff line change
Expand Up @@ -110,25 +110,34 @@ static int process_commit_parents(git_revwalk *walk, git_commit_list_node *commi
return error;
}

static int push_commit(git_revwalk *walk, const git_oid *oid, int uninteresting)
static int push_commit(git_revwalk *walk, const git_oid *oid, int uninteresting, int from_glob)
{
git_oid commit_id;
int error;
git_object *obj;
git_otype type;
git_object *obj, *oobj;
git_commit_list_node *commit;

if ((error = git_object_lookup(&obj, walk->repo, oid, GIT_OBJ_ANY)) < 0)
if ((error = git_object_lookup(&oobj, walk->repo, oid, GIT_OBJ_ANY)) < 0)
return error;

type = git_object_type(obj);
git_object_free(obj);
error = git_object_peel(&obj, oobj, GIT_OBJ_COMMIT);
git_object_free(oobj);

if (error == GIT_ENOTFOUND) {
/* If this comes from e.g. push_glob("tags"), ignore this */
if (from_glob)
return 0;

if (type != GIT_OBJ_COMMIT) {
giterr_set(GITERR_INVALID, "Object is no commit object");
giterr_set(GITERR_INVALID, "Object is not a committish");
return -1;
}
if (error < 0)
return error;

git_oid_cpy(&commit_id, git_object_id(obj));
git_object_free(obj);

commit = git_revwalk__commit_lookup(walk, oid);
commit = git_revwalk__commit_lookup(walk, &commit_id);
if (commit == NULL)
return -1; /* error already reported by failed lookup */

Expand All @@ -146,42 +155,37 @@ static int push_commit(git_revwalk *walk, const git_oid *oid, int uninteresting)
int git_revwalk_push(git_revwalk *walk, const git_oid *oid)
{
assert(walk && oid);
return push_commit(walk, oid, 0);
return push_commit(walk, oid, 0, false);
}


int git_revwalk_hide(git_revwalk *walk, const git_oid *oid)
{
assert(walk && oid);
return push_commit(walk, oid, 1);
return push_commit(walk, oid, 1, false);
}

static int push_ref(git_revwalk *walk, const char *refname, int hide)
static int push_ref(git_revwalk *walk, const char *refname, int hide, int from_glob)
{
git_oid oid;

if (git_reference_name_to_id(&oid, walk->repo, refname) < 0)
return -1;

return push_commit(walk, &oid, hide);
return push_commit(walk, &oid, hide, from_glob);
}

struct push_cb_data {
git_revwalk *walk;
int hide;
};

static int push_glob_cb(const char *refname, void *data_)
{
struct push_cb_data *data = (struct push_cb_data *)data_;
return push_ref(data->walk, refname, data->hide);
}

static int push_glob(git_revwalk *walk, const char *glob, int hide)
{
int error = 0;
git_buf buf = GIT_BUF_INIT;
struct push_cb_data data;
git_reference *ref;
git_reference_iterator *iter;
size_t wildcard;

assert(walk && glob);
Expand All @@ -199,12 +203,20 @@ static int push_glob(git_revwalk *walk, const char *glob, int hide)
if (!glob[wildcard])
git_buf_put(&buf, "/*", 2);

data.walk = walk;
data.hide = hide;
if ((error = git_reference_iterator_glob_new(&iter, walk->repo, buf.ptr)) < 0)
goto out;

error = git_reference_foreach_glob(
walk->repo, git_buf_cstr(&buf), push_glob_cb, &data);
while ((error = git_reference_next(&ref, iter)) == 0) {
error = push_ref(walk, git_reference_name(ref), hide, true);
git_reference_free(ref);
if (error < 0)
break;
}
git_reference_iterator_free(iter);

if (error == GIT_ITEROVER)
error = 0;
out:
git_buf_free(&buf);
return error;
}
Expand All @@ -224,19 +236,19 @@ int git_revwalk_hide_glob(git_revwalk *walk, const char *glob)
int git_revwalk_push_head(git_revwalk *walk)
{
assert(walk);
return push_ref(walk, GIT_HEAD_FILE, 0);
return push_ref(walk, GIT_HEAD_FILE, 0, false);
}

int git_revwalk_hide_head(git_revwalk *walk)
{
assert(walk);
return push_ref(walk, GIT_HEAD_FILE, 1);
return push_ref(walk, GIT_HEAD_FILE, 1, false);
}

int git_revwalk_push_ref(git_revwalk *walk, const char *refname)
{
assert(walk && refname);
return push_ref(walk, refname, 0);
return push_ref(walk, refname, 0, false);
}

int git_revwalk_push_range(git_revwalk *walk, const char *range)
Expand All @@ -253,10 +265,10 @@ int git_revwalk_push_range(git_revwalk *walk, const char *range)
return GIT_EINVALIDSPEC;
}

if ((error = push_commit(walk, git_object_id(revspec.from), 1)))
if ((error = push_commit(walk, git_object_id(revspec.from), 1, false)))
goto out;

error = push_commit(walk, git_object_id(revspec.to), 0);
error = push_commit(walk, git_object_id(revspec.to), 0, false);

out:
git_object_free(revspec.from);
Expand All @@ -267,7 +279,7 @@ int git_revwalk_push_range(git_revwalk *walk, const char *range)
int git_revwalk_hide_ref(git_revwalk *walk, const char *refname)
{
assert(walk && refname);
return push_ref(walk, refname, 1);
return push_ref(walk, refname, 1, false);
}

static int revwalk_enqueue_timesort(git_revwalk *walk, git_commit_list_node *commit)
Expand Down
23 changes: 23 additions & 0 deletions src/strnlen.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/*
* Copyright (C) the libgit2 contributors. All rights reserved.
*
* 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_strlen_h__
#define INCLUDE_strlen_h__

#if defined(__MINGW32__) || defined(__sun) || defined(__APPLE__)
# define NO_STRNLEN
#endif

#ifdef NO_STRNLEN
GIT_INLINE(size_t) p_strnlen(const char *s, size_t maxlen) {
const char *end = memchr(s, 0, maxlen);
return end ? (size_t)(end - s) : maxlen;
}
#else
# define p_strnlen strnlen
#endif

#endif
Loading

0 comments on commit 0de2c4e

Please sign in to comment.