Commit 0de2c4e3 by Ben Straub

Merge remote-tracking branch 'libgit2/development' into bs/more-reflog-stuff

parents 010cec3a 629ba7f1
......@@ -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
......@@ -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
......@@ -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
......@@ -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
......@@ -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
......@@ -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
......
......@@ -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;
......@@ -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;
......@@ -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) {
......
......@@ -2330,7 +2330,7 @@ done:
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;
......@@ -2341,9 +2341,6 @@ 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.
......@@ -2351,13 +2348,13 @@ static int merge_check_workdir(size_t *conflicts, git_repository *repo, git_inde
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;
......@@ -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;
......
......@@ -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>
......
......@@ -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;
......
......@@ -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 */
......@@ -146,24 +155,24 @@ 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 {
......@@ -171,17 +180,12 @@ struct push_cb_data {
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);
......@@ -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;
}
......@@ -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)
......@@ -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);
......@@ -267,7 +279,7 @@ out:
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)
......
/*
* 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
......@@ -8,6 +8,7 @@
#define INCLUDE_util_h__
#include "common.h"
#include "strnlen.h"
#define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0]))
#define bitsizeof(x) (CHAR_BIT * sizeof(x))
......@@ -50,8 +51,7 @@ GIT_INLINE(char *) git__strndup(const char *str, size_t n)
size_t length = 0;
char *ptr;
while (length < n && str[length])
++length;
length = p_strnlen(str, n);
ptr = (char*)git__malloc(length + 1);
......
#include "clar_libgit2.h"
#include "git2/merge.h"
#include "buffer.h"
#include "merge.h"
#include "../merge_helpers.h"
#include "posix.h"
#define TEST_REPO_PATH "merge-resolve"
#define MERGE_BRANCH_OID "7cb63eed597130ba4abb87b3e544b85021905520"
#define AUTOMERGEABLE_MERGED_FILE \
"this file is changed in master\n" \
"this file is automergeable\n" \
"this file is automergeable\n" \
"this file is automergeable\n" \
"this file is automergeable\n" \
"this file is automergeable\n" \
"this file is automergeable\n" \
"this file is automergeable\n" \
"this file is changed in branch\n"
#define CHANGED_IN_BRANCH_FILE \
"changed in branch\n"
static git_repository *repo;
static git_index *repo_index;
static char *unaffected[][4] = {
{ "added-in-master.txt", NULL },
{ "changed-in-master.txt", NULL },
{ "unchanged.txt", NULL },
{ "added-in-master.txt", "changed-in-master.txt", NULL },
{ "added-in-master.txt", "unchanged.txt", NULL },
{ "changed-in-master.txt", "unchanged.txt", NULL },
{ "added-in-master.txt", "changed-in-master.txt", "unchanged.txt", NULL },
{ "new_file.txt", NULL },
{ "new_file.txt", "unchanged.txt", NULL },
{ NULL },
};
static char *affected[][5] = {
{ "automergeable.txt", NULL },
{ "changed-in-branch.txt", NULL },
{ "conflicting.txt", NULL },
{ "removed-in-branch.txt", NULL },
{ "automergeable.txt", "changed-in-branch.txt", NULL },
{ "automergeable.txt", "conflicting.txt", NULL },
{ "automergeable.txt", "removed-in-branch.txt", NULL },
{ "changed-in-branch.txt", "conflicting.txt", NULL },
{ "changed-in-branch.txt", "removed-in-branch.txt", NULL },
{ "conflicting.txt", "removed-in-branch.txt", NULL },
{ "automergeable.txt", "changed-in-branch.txt", "conflicting.txt", NULL },
{ "automergeable.txt", "changed-in-branch.txt", "removed-in-branch.txt", NULL },
{ "automergeable.txt", "conflicting.txt", "removed-in-branch.txt", NULL },
{ "changed-in-branch.txt", "conflicting.txt", "removed-in-branch.txt", NULL },
{ "automergeable.txt", "changed-in-branch.txt", "conflicting.txt", "removed-in-branch.txt", NULL },
{ NULL },
};
static char *result_contents[4][6] = {
{ "automergeable.txt", AUTOMERGEABLE_MERGED_FILE, NULL, NULL },
{ "changed-in-branch.txt", CHANGED_IN_BRANCH_FILE, NULL, NULL },
{ "automergeable.txt", AUTOMERGEABLE_MERGED_FILE, "changed-in-branch.txt", CHANGED_IN_BRANCH_FILE, NULL, NULL },
{ NULL }
};
void test_merge_workdir_dirty__initialize(void)
{
repo = cl_git_sandbox_init(TEST_REPO_PATH);
git_repository_index(&repo_index, repo);
}
void test_merge_workdir_dirty__cleanup(void)
{
git_index_free(repo_index);
cl_git_sandbox_cleanup();
}
static void set_core_autocrlf_to(git_repository *repo, bool value)
{
git_config *cfg;
cl_git_pass(git_repository_config(&cfg, repo));
cl_git_pass(git_config_set_bool(cfg, "core.autocrlf", value));
git_config_free(cfg);
}
static int merge_branch(git_merge_result **result, int merge_file_favor, int checkout_strategy)
{
git_oid their_oids[1];
git_merge_head *their_heads[1];
git_merge_opts opts = GIT_MERGE_OPTS_INIT;
int error;
cl_git_pass(git_oid_fromstr(&their_oids[0], MERGE_BRANCH_OID));
cl_git_pass(git_merge_head_from_id(&their_heads[0], repo, &their_oids[0]));
opts.merge_tree_opts.file_favor = merge_file_favor;
opts.checkout_opts.checkout_strategy = checkout_strategy;
error = git_merge(result, repo, (const git_merge_head **)their_heads, 1, &opts);
git_merge_head_free(their_heads[0]);
return error;
}
static void write_files(char *files[])
{
char *filename;
git_buf path = GIT_BUF_INIT, content = GIT_BUF_INIT;
size_t i;
for (i = 0, filename = files[i]; filename; filename = files[++i]) {
git_buf_clear(&path);
git_buf_clear(&content);
git_buf_printf(&path, "%s/%s", TEST_REPO_PATH, filename);
git_buf_printf(&content, "This is a dirty file in the working directory!\n\n"
"It will not be staged! Its filename is %s.\n", filename);
cl_git_mkfile(path.ptr, content.ptr);
}
git_buf_free(&path);
git_buf_free(&content);
}
static void hack_index(char *files[])
{
char *filename;
struct stat statbuf;
git_buf path = GIT_BUF_INIT;
git_index_entry *entry;
size_t i;
/* Update the index to suggest that checkout placed these files on
* disk, keeping the object id but updating the cache, which will
* emulate a Git implementation's different filter.
*/
for (i = 0, filename = files[i]; filename; filename = files[++i]) {
git_buf_clear(&path);
cl_assert(entry = (git_index_entry *)
git_index_get_bypath(repo_index, filename, 0));
cl_git_pass(git_buf_printf(&path, "%s/%s", TEST_REPO_PATH, filename));
cl_git_pass(p_stat(path.ptr, &statbuf));
entry->ctime.seconds = (git_time_t)statbuf.st_ctime;
entry->ctime.nanoseconds = 0;
entry->mtime.seconds = (git_time_t)statbuf.st_mtime;
entry->mtime.nanoseconds = 0;
entry->dev = statbuf.st_dev;
entry->ino = statbuf.st_ino;
entry->uid = statbuf.st_uid;
entry->gid = statbuf.st_gid;
entry->file_size = statbuf.st_size;
}
git_buf_free(&path);
}
static void stage_random_files(char *files[])
{
char *filename;
size_t i;
write_files(files);
for (i = 0, filename = files[i]; filename; filename = files[++i])
cl_git_pass(git_index_add_bypath(repo_index, filename));
}
static void stage_content(char *content[])
{
git_reference *head;
git_object *head_object;
git_merge_result *result = NULL;
git_buf path = GIT_BUF_INIT;
char *filename, *text;
size_t i;
cl_git_pass(git_repository_head(&head, repo));
cl_git_pass(git_reference_peel(&head_object, head, GIT_OBJ_COMMIT));
cl_git_pass(git_reset(repo, head_object, GIT_RESET_HARD));
for (i = 0, filename = content[i], text = content[++i];
filename && text;
filename = content[++i], text = content[++i]) {
git_buf_clear(&path);
cl_git_pass(git_buf_printf(&path, "%s/%s", TEST_REPO_PATH, filename));
cl_git_mkfile(path.ptr, text);
cl_git_pass(git_index_add_bypath(repo_index, filename));
}
git_merge_result_free(result);
git_object_free(head_object);
git_reference_free(head);
git_buf_free(&path);
}
static int merge_dirty_files(char *dirty_files[])
{
git_reference *head;
git_object *head_object;
git_merge_result *result = NULL;
int error;
cl_git_pass(git_repository_head(&head, repo));
cl_git_pass(git_reference_peel(&head_object, head, GIT_OBJ_COMMIT));
cl_git_pass(git_reset(repo, head_object, GIT_RESET_HARD));
write_files(dirty_files);
error = merge_branch(&result, 0, 0);
git_merge_result_free(result);
git_object_free(head_object);
git_reference_free(head);
return error;
}
static int merge_differently_filtered_files(char *files[])
{
git_reference *head;
git_object *head_object;
git_merge_result *result = NULL;
int error;
cl_git_pass(git_repository_head(&head, repo));
cl_git_pass(git_reference_peel(&head_object, head, GIT_OBJ_COMMIT));
cl_git_pass(git_reset(repo, head_object, GIT_RESET_HARD));
write_files(files);
hack_index(files);
cl_git_pass(git_index_write(repo_index));
error = merge_branch(&result, 0, 0);
git_merge_result_free(result);
git_object_free(head_object);
git_reference_free(head);
return error;
}
static int merge_staged_files(char *staged_files[])
{
git_merge_result *result = NULL;
int error;
stage_random_files(staged_files);
error = merge_branch(&result, 0, 0);
git_merge_result_free(result);
return error;
}
void test_merge_workdir_dirty__unaffected_dirty_files_allowed(void)
{
char **files;
size_t i;
for (i = 0, files = unaffected[i]; files[0]; files = unaffected[++i])
cl_git_pass(merge_dirty_files(files));
}
void test_merge_workdir_dirty__affected_dirty_files_disallowed(void)
{
char **files;
size_t i;
for (i = 0, files = affected[i]; files[0]; files = affected[++i])
cl_git_fail(merge_dirty_files(files));
}
void test_merge_workdir_dirty__staged_files_in_index_disallowed(void)
{
char **files;
size_t i;
for (i = 0, files = unaffected[i]; files[0]; files = unaffected[++i])
cl_git_fail(merge_staged_files(files));
for (i = 0, files = affected[i]; files[0]; files = affected[++i])
cl_git_fail(merge_staged_files(files));
}
void test_merge_workdir_dirty__identical_staged_files_allowed(void)
{
git_merge_result *result;
char **content;
size_t i;
set_core_autocrlf_to(repo, false);
for (i = 0, content = result_contents[i]; content[0]; content = result_contents[++i]) {
stage_content(content);
git_index_write(repo_index);
cl_git_pass(merge_branch(&result, 0, 0));
git_merge_result_free(result);
}
}
void test_merge_workdir_dirty__honors_cache(void)
{
char **files;
size_t i;
for (i = 0, files = affected[i]; files[0]; files = affected[++i])
cl_git_pass(merge_differently_filtered_files(files));
}
......@@ -9,7 +9,7 @@ static const char *third_tree = "eb86d8b81d6adbd5290a935d6c9976882de98488";
static git_repository *g_repo;
// Fixture setup and teardown
/* Fixture setup and teardown */
void test_object_tree_write__initialize(void)
{
g_repo = cl_git_sandbox_init("testrepo");
......@@ -22,7 +22,7 @@ void test_object_tree_write__cleanup(void)
void test_object_tree_write__from_memory(void)
{
// write a tree from a memory
/* write a tree from a memory */
git_treebuilder *builder;
git_tree *tree;
git_oid id, bid, rid, id2;
......@@ -31,7 +31,9 @@ void test_object_tree_write__from_memory(void)
git_oid_fromstr(&id2, second_tree);
git_oid_fromstr(&bid, blob_oid);
//create a second tree from first tree using `git_treebuilder_insert` on REPOSITORY_FOLDER.
/* create a second tree from first tree using `git_treebuilder_insert`
* on REPOSITORY_FOLDER.
*/
cl_git_pass(git_tree_lookup(&tree, g_repo, &id));
cl_git_pass(git_treebuilder_create(&builder, tree));
......@@ -61,7 +63,7 @@ void test_object_tree_write__from_memory(void)
void test_object_tree_write__subtree(void)
{
// write a hierarchical tree from a memory
/* write a hierarchical tree from a memory */
git_treebuilder *builder;
git_tree *tree;
git_oid id, bid, subtree_id, id2, id3;
......@@ -72,25 +74,25 @@ void test_object_tree_write__subtree(void)
git_oid_fromstr(&id3, third_tree);
git_oid_fromstr(&bid, blob_oid);
//create subtree
/* create subtree */
cl_git_pass(git_treebuilder_create(&builder, NULL));
cl_git_pass(git_treebuilder_insert(
NULL, builder, "new.txt", &bid, GIT_FILEMODE_BLOB)); //-V536
NULL, builder, "new.txt", &bid, GIT_FILEMODE_BLOB)); /* -V536 */
cl_git_pass(git_treebuilder_write(&subtree_id, g_repo, builder));
git_treebuilder_free(builder);
// create parent tree
/* create parent tree */
cl_git_pass(git_tree_lookup(&tree, g_repo, &id));
cl_git_pass(git_treebuilder_create(&builder, tree));
cl_git_pass(git_treebuilder_insert(
NULL, builder, "new", &subtree_id, GIT_FILEMODE_TREE)); //-V536
NULL, builder, "new", &subtree_id, GIT_FILEMODE_TREE)); /* -V536 */
cl_git_pass(git_treebuilder_write(&id_hiearar, g_repo, builder));
git_treebuilder_free(builder);
git_tree_free(tree);
cl_assert(git_oid_cmp(&id_hiearar, &id3) == 0);
// check data is correct
/* check data is correct */
cl_git_pass(git_tree_lookup(&tree, g_repo, &id_hiearar));
cl_assert(2 == git_tree_entrycount(tree));
git_tree_free(tree);
......@@ -314,3 +316,83 @@ void test_object_tree_write__filtering(void)
git_tree_free(tree);
}
void test_object_tree_write__cruel_paths(void)
{
static const char *the_paths[] = {
"C:\\",
" : * ? \" \n < > |",
"a\\b",
"\\\\b\a",
":\\",
"COM1",
"foo.aux",
REP1024("1234"), /* 4096 char string */
REP1024("12345678"), /* 8192 char string */
"\xC5\xAA\x6E\xC4\xAD\x63\xC5\x8D\x64\x65\xCC\xBD", /* Ūnĭcōde̽ */
NULL
};
git_treebuilder *builder;
git_tree *tree;
git_oid id, bid, subid;
const char **scan;
int count = 0, i, j;
git_tree_entry *te;
git_oid_fromstr(&bid, blob_oid);
/* create tree */
cl_git_pass(git_treebuilder_create(&builder, NULL));
for (scan = the_paths; *scan; ++scan) {
cl_git_pass(git_treebuilder_insert(
NULL, builder, *scan, &bid, GIT_FILEMODE_BLOB));
count++;
}
cl_git_pass(git_treebuilder_write(&id, g_repo, builder));
git_treebuilder_free(builder);
/* check data is correct */
cl_git_pass(git_tree_lookup(&tree, g_repo, &id));
cl_assert_equal_i(count, git_tree_entrycount(tree));
for (scan = the_paths; *scan; ++scan) {
const git_tree_entry *cte = git_tree_entry_byname(tree, *scan);
cl_assert(cte != NULL);
cl_assert_equal_s(*scan, git_tree_entry_name(cte));
}
for (scan = the_paths; *scan; ++scan) {
cl_git_pass(git_tree_entry_bypath(&te, tree, *scan));
cl_assert_equal_s(*scan, git_tree_entry_name(te));
git_tree_entry_free(te);
}
git_tree_free(tree);
/* let's try longer paths */
cl_git_pass(git_treebuilder_create(&builder, NULL));
for (scan = the_paths; *scan; ++scan) {
cl_git_pass(git_treebuilder_insert(
NULL, builder, *scan, &id, GIT_FILEMODE_TREE));
}
cl_git_pass(git_treebuilder_write(&subid, g_repo, builder));
git_treebuilder_free(builder);
/* check data is correct */
cl_git_pass(git_tree_lookup(&tree, g_repo, &subid));
cl_assert_equal_i(count, git_tree_entrycount(tree));
for (i = 0; i < count; ++i) {
for (j = 0; j < count; ++j) {
git_buf b = GIT_BUF_INIT;
cl_git_pass(git_buf_joinpath(&b, the_paths[i], the_paths[j]));
cl_git_pass(git_tree_entry_bypath(&te, tree, b.ptr));
cl_assert_equal_s(the_paths[j], git_tree_entry_name(te));
git_tree_entry_free(te);
git_buf_free(&b);
}
}
git_tree_free(tree);
}
......@@ -252,3 +252,41 @@ void test_revwalk_basic__push_range(void)
cl_git_pass(git_revwalk_push_range(_walk, "9fd738e~2..9fd738e"));
cl_git_pass(test_walk_only(_walk, commit_sorting_segment, 1));
}
void test_revwalk_basic__push_mixed(void)
{
git_oid oid;
int i = 0;
revwalk_basic_setup_walk(NULL);
git_revwalk_reset(_walk);
git_revwalk_sorting(_walk, 0);
cl_git_pass(git_revwalk_push_glob(_walk, "tags"));
while (git_revwalk_next(&oid, _walk) == 0) {
i++;
}
/* git rev-list --count --glob=tags #=> 9 */
cl_assert_equal_i(9, i);
}
void test_revwalk_basic__push_all(void)
{
git_oid oid;
int i = 0;
revwalk_basic_setup_walk(NULL);
git_revwalk_reset(_walk);
git_revwalk_sorting(_walk, 0);
cl_git_pass(git_revwalk_push_glob(_walk, "*"));
while (git_revwalk_next(&oid, _walk) == 0) {
i++;
}
/* git rev-list --count --all #=> 15 */
cl_assert_equal_i(15, i);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment