void test_object_tree_write__subtree(void) { // write a hierarchical tree from a memory git_treebuilder *builder; git_tree *tree; git_oid id, bid, subtree_id, id2, id3; git_oid id_hiearar; git_oid_fromstr(&id, first_tree); git_oid_fromstr(&id2, second_tree); git_oid_fromstr(&id3, third_tree); git_oid_fromstr(&bid, blob_oid); //create subtree cl_git_pass(git_treebuilder_create(&builder, NULL)); cl_git_pass(git_treebuilder_insert(NULL,builder,"new.txt",&bid,0100644)); cl_git_pass(git_treebuilder_write(&subtree_id, g_repo, builder)); git_treebuilder_free(builder); // 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,040000)); 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 cl_git_pass(git_tree_lookup(&tree, g_repo, &id_hiearar)); cl_assert(2 == git_tree_entrycount(tree)); git_tree_free(tree); }
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_create(git_treebuilder **builder_p, const git_tree *source) { git_treebuilder *bld; unsigned int 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) { for (i = 0; i < source->entries.length; ++i) { git_tree_entry *entry_src = source->entries.contents[i]; if (append_entry(bld, entry_src->filename, &entry_src->oid, entry_src->attr) < 0) { git_treebuilder_free(bld); return GIT_ENOMEM; } } } *builder_p = bld; return GIT_SUCCESS; }
void TreeBuilder_dealloc(TreeBuilder* self) { Py_XDECREF(self->repo); git_treebuilder_free(self->bld); PyObject_Del(self); }
void test_object_tree_write__from_memory(void) { // write a tree from a memory git_treebuilder *builder; git_tree *tree; git_oid id, bid, rid, id2; git_oid_fromstr(&id, first_tree); 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. cl_git_pass(git_tree_lookup(&tree, g_repo, &id)); cl_git_pass(git_treebuilder_create(&builder, tree)); cl_git_fail(git_treebuilder_insert(NULL, builder, "", &bid, 0100644)); cl_git_fail(git_treebuilder_insert(NULL, builder, "/", &bid, 0100644)); cl_git_fail(git_treebuilder_insert(NULL, builder, "folder/new.txt", &bid, 0100644)); cl_git_pass(git_treebuilder_insert(NULL,builder,"new.txt",&bid,0100644)); cl_git_pass(git_treebuilder_write(&rid, g_repo, builder)); cl_assert(git_oid_cmp(&rid, &id2) == 0); git_treebuilder_free(builder); git_tree_free(tree); }
void test_object_tree_attributes__normalize_attributes_when_creating_a_tree_from_an_existing_one(void) { git_repository *repo; git_treebuilder *builder; git_oid tid, tid2; git_tree *tree; const git_tree_entry *entry; repo = cl_git_sandbox_init("deprecated-mode.git"); cl_git_pass(git_oid_fromstr(&tid, tree_oid)); cl_git_pass(git_tree_lookup(&tree, repo, &tid)); cl_git_pass(git_treebuilder_create(&builder, tree)); entry = git_treebuilder_get(builder, "old_mode.txt"); cl_assert_equal_i( GIT_FILEMODE_BLOB, git_tree_entry_filemode(entry)); cl_git_pass(git_treebuilder_write(&tid2, repo, builder)); git_treebuilder_free(builder); git_tree_free(tree); cl_git_pass(git_tree_lookup(&tree, repo, &tid2)); entry = git_tree_entry_byname(tree, "old_mode.txt"); cl_assert_equal_i( GIT_FILEMODE_BLOB, git_tree_entry_filemode(entry)); git_tree_free(tree); cl_git_sandbox_cleanup(); }
static int tree_write( git_tree **out, git_repository *repo, git_tree *source_tree, const git_oid *object_oid, const char *treeentry_name, unsigned int attributes) { int error; git_treebuilder *tb = NULL; const git_tree_entry *entry; git_oid tree_oid; if ((error = git_treebuilder_create(&tb, source_tree)) < 0) goto cleanup; if (object_oid) { if ((error = git_treebuilder_insert( &entry, tb, treeentry_name, object_oid, attributes)) < 0) goto cleanup; } else { if ((error = git_treebuilder_remove(tb, treeentry_name)) < 0) goto cleanup; } if ((error = git_treebuilder_write(&tree_oid, repo, tb)) < 0) goto cleanup; error = git_tree_lookup(out, repo, &tree_oid); cleanup: git_treebuilder_free(tb); return error; }
static void test_inserting_submodule(void) { git_treebuilder *bld; git_oid sm_id; cl_git_pass(git_oid_fromstr(&sm_id, "da39a3ee5e6b4b0d3255bfef95601890afd80709")); cl_git_pass(git_treebuilder_new(&bld, g_repo, NULL)); cl_git_pass(git_treebuilder_insert(NULL, bld, "sm", &sm_id, GIT_FILEMODE_COMMIT)); git_treebuilder_free(bld); }
void test_object_tree_write__invalid_null_oid(void) { git_treebuilder *bld; git_oid null_oid = {{0}}; cl_git_pass(git_treebuilder_new(&bld, g_repo, NULL)); cl_git_fail(git_treebuilder_insert(NULL, bld, "null_oid_file", &null_oid, GIT_FILEMODE_BLOB)); cl_assert(giterr_last() && strstr(giterr_last()->message, "null OID") != NULL); git_treebuilder_free(bld); }
void test_object_tree_write__protect_filesystems(void) { git_treebuilder *builder; git_oid bid; cl_git_pass(git_oid_fromstr(&bid, "fa49b077972391ad58037050f2a75f74e3671e92")); /* Ensure that (by default) we can write objects with funny names on * platforms that are not affected. */ cl_git_pass(git_treebuilder_new(&builder, g_repo, NULL)); #ifndef GIT_WIN32 cl_git_pass(git_treebuilder_insert(NULL, builder, ".git.", &bid, GIT_FILEMODE_BLOB)); cl_git_pass(git_treebuilder_insert(NULL, builder, "git~1", &bid, GIT_FILEMODE_BLOB)); #endif #ifndef __APPLE__ cl_git_pass(git_treebuilder_insert(NULL, builder, ".git\xef\xbb\xbf", &bid, GIT_FILEMODE_BLOB)); cl_git_pass(git_treebuilder_insert(NULL, builder, ".git\xe2\x80\xad", &bid, GIT_FILEMODE_BLOB)); #endif git_treebuilder_free(builder); /* Now turn on core.protectHFS and core.protectNTFS and validate that these * paths are rejected. */ cl_repo_set_bool(g_repo, "core.protectHFS", true); cl_repo_set_bool(g_repo, "core.protectNTFS", true); cl_git_pass(git_treebuilder_new(&builder, g_repo, NULL)); cl_git_fail(git_treebuilder_insert(NULL, builder, ".git.", &bid, GIT_FILEMODE_BLOB)); cl_git_fail(git_treebuilder_insert(NULL, builder, "git~1", &bid, GIT_FILEMODE_BLOB)); cl_git_fail(git_treebuilder_insert(NULL, builder, ".git\xef\xbb\xbf", &bid, GIT_FILEMODE_BLOB)); cl_git_fail(git_treebuilder_insert(NULL, builder, ".git\xe2\x80\xad", &bid, GIT_FILEMODE_BLOB)); git_treebuilder_free(builder); }
void test_object_tree_write__subtree(void) { /* write a hierarchical tree from a memory */ git_treebuilder *builder; git_tree *tree; git_oid id, bid, subtree_id, id2, id3; git_oid id_hiearar; git_oid_fromstr(&id, first_tree); git_oid_fromstr(&id2, second_tree); git_oid_fromstr(&id3, third_tree); git_oid_fromstr(&bid, blob_oid); /* create subtree */ cl_git_pass(git_treebuilder_new(&builder, g_repo, NULL)); cl_git_pass(git_treebuilder_insert( NULL, builder, "new.txt", &bid, GIT_FILEMODE_BLOB)); /* -V536 */ cl_git_pass(git_treebuilder_write(&subtree_id, builder)); git_treebuilder_free(builder); /* create parent tree */ cl_git_pass(git_tree_lookup(&tree, g_repo, &id)); cl_git_pass(git_treebuilder_new(&builder, g_repo, tree)); cl_git_pass(git_treebuilder_insert( NULL, builder, "new", &subtree_id, GIT_FILEMODE_TREE)); /* -V536 */ cl_git_pass(git_treebuilder_write(&id_hiearar, builder)); git_treebuilder_free(builder); git_tree_free(tree); cl_assert(git_oid_cmp(&id_hiearar, &id3) == 0); /* 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); }
void test_object_tree_attributes__ensure_correctness_of_attributes_on_insertion(void) { git_treebuilder *builder; git_oid oid; cl_git_pass(git_oid_fromstr(&oid, blob_oid)); cl_git_pass(git_treebuilder_create(&builder, NULL)); cl_git_fail(git_treebuilder_insert(NULL, builder, "one.txt", &oid, (git_filemode_t)0777777)); cl_git_fail(git_treebuilder_insert(NULL, builder, "one.txt", &oid, (git_filemode_t)0100666)); cl_git_fail(git_treebuilder_insert(NULL, builder, "one.txt", &oid, (git_filemode_t)0000001)); git_treebuilder_free(builder); }
static VALUE backend_write_tree(VALUE rb_obj, VALUE rb_hash) { git_oid oid; int error; git_treebuilder *bld; git_treebuilder_create(&bld, NULL); rb_hash_foreach(rb_hash, backend_add_tree_entry, (VALUE)bld); error = git_treebuilder_odb_write(&oid, DATA_PTR(rb_obj), bld); git_treebuilder_free(bld); backend_exception_check(error); return backend_create_oid(&oid); }
void test_object_tree_write__filtering(void) { git_treebuilder *builder; int i; git_oid entry_oid, tree_oid; git_tree *tree; git_oid_fromstr(&entry_oid, blob_oid); cl_git_pass(git_treebuilder_new(&builder, g_repo, NULL)); for (i = 0; _entries[i].filename; ++i) cl_git_pass(git_treebuilder_insert(NULL, builder, _entries[i].filename, &entry_oid, _entries[i].attr)); cl_assert_equal_i(6, (int)git_treebuilder_entrycount(builder)); cl_assert(git_treebuilder_get(builder, "apple") != NULL); cl_assert(git_treebuilder_get(builder, "aardvark") != NULL); cl_assert(git_treebuilder_get(builder, "last") != NULL); git_treebuilder_filter(builder, treebuilder_filter_prefixed, "apple"); cl_assert_equal_i(4, (int)git_treebuilder_entrycount(builder)); cl_assert(git_treebuilder_get(builder, "apple") == NULL); cl_assert(git_treebuilder_get(builder, "aardvark") != NULL); cl_assert(git_treebuilder_get(builder, "last") != NULL); git_treebuilder_filter(builder, treebuilder_filter_prefixed, "a"); cl_assert_equal_i(2, (int)git_treebuilder_entrycount(builder)); cl_assert(git_treebuilder_get(builder, "aardvark") == NULL); cl_assert(git_treebuilder_get(builder, "last") != NULL); cl_git_pass(git_treebuilder_write(&tree_oid, builder)); git_treebuilder_free(builder); cl_git_pass(git_tree_lookup(&tree, g_repo, &tree_oid)); cl_assert_equal_i(2, (int)git_tree_entrycount(tree)); git_tree_free(tree); }
void test_object_tree_attributes__treebuilder_reject_invalid_filemode(void) { git_treebuilder *builder; git_oid bid; const git_tree_entry *entry; cl_git_pass(git_oid_fromstr(&bid, blob_oid)); cl_git_pass(git_treebuilder_create(&builder, NULL)); cl_git_fail(git_treebuilder_insert( &entry, builder, "normalized.txt", &bid, GIT_FILEMODE_BLOB_GROUP_WRITABLE)); git_treebuilder_free(builder); }
static void test_invalid_objects(bool should_allow_invalid) { git_treebuilder *builder; git_oid valid_blob_id, invalid_blob_id, valid_tree_id, invalid_tree_id; #define assert_allowed(expr) \ clar__assert(!(expr) == should_allow_invalid, __FILE__, __LINE__, \ (should_allow_invalid ? \ "Expected function call to succeed: " #expr : \ "Expected function call to fail: " #expr), \ NULL, 1) cl_git_pass(git_oid_fromstr(&valid_blob_id, blob_oid)); cl_git_pass(git_oid_fromstr(&invalid_blob_id, "1234567890123456789012345678901234567890")); cl_git_pass(git_oid_fromstr(&valid_tree_id, first_tree)); cl_git_pass(git_oid_fromstr(&invalid_tree_id, "0000000000111111111122222222223333333333")); cl_git_pass(git_treebuilder_new(&builder, g_repo, NULL)); /* test valid blobs and trees (these should always pass) */ cl_git_pass(git_treebuilder_insert(NULL, builder, "file.txt", &valid_blob_id, GIT_FILEMODE_BLOB)); cl_git_pass(git_treebuilder_insert(NULL, builder, "folder", &valid_tree_id, GIT_FILEMODE_TREE)); /* replace valid files and folders with invalid ones */ assert_allowed(git_treebuilder_insert(NULL, builder, "file.txt", &invalid_blob_id, GIT_FILEMODE_BLOB)); assert_allowed(git_treebuilder_insert(NULL, builder, "folder", &invalid_blob_id, GIT_FILEMODE_BLOB)); /* insert new invalid files and folders */ assert_allowed(git_treebuilder_insert(NULL, builder, "invalid_file.txt", &invalid_blob_id, GIT_FILEMODE_BLOB)); assert_allowed(git_treebuilder_insert(NULL, builder, "invalid_folder", &invalid_blob_id, GIT_FILEMODE_BLOB)); /* insert valid blobs as trees and trees as blobs */ assert_allowed(git_treebuilder_insert(NULL, builder, "file_as_folder", &valid_blob_id, GIT_FILEMODE_TREE)); assert_allowed(git_treebuilder_insert(NULL, builder, "folder_as_file.txt", &valid_tree_id, GIT_FILEMODE_BLOB)); #undef assert_allowed git_treebuilder_free(builder); }
void test_object_tree_write__from_memory(void) { /* write a tree from a memory */ git_treebuilder *builder; git_tree *tree; git_oid id, bid, rid, id2; git_oid_fromstr(&id, first_tree); 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. */ cl_git_pass(git_tree_lookup(&tree, g_repo, &id)); cl_git_pass(git_treebuilder_new(&builder, g_repo, tree)); cl_git_fail(git_treebuilder_insert(NULL, builder, "", &bid, GIT_FILEMODE_BLOB)); cl_git_fail(git_treebuilder_insert(NULL, builder, "/", &bid, GIT_FILEMODE_BLOB)); cl_git_fail(git_treebuilder_insert(NULL, builder, ".git", &bid, GIT_FILEMODE_BLOB)); cl_git_fail(git_treebuilder_insert(NULL, builder, "..", &bid, GIT_FILEMODE_BLOB)); cl_git_fail(git_treebuilder_insert(NULL, builder, ".", &bid, GIT_FILEMODE_BLOB)); cl_git_fail(git_treebuilder_insert(NULL, builder, "folder/new.txt", &bid, GIT_FILEMODE_BLOB)); cl_git_pass(git_treebuilder_insert( NULL, builder, "new.txt", &bid, GIT_FILEMODE_BLOB)); cl_git_pass(git_treebuilder_write(&rid, builder)); cl_assert(git_oid_cmp(&rid, &id2) == 0); git_treebuilder_free(builder); git_tree_free(tree); }
/* "b=name,t=name", blob_id, tree_id */ static void build_test_tree( git_oid *out, git_repository *repo, const char *fmt, ...) { git_oid *id; git_treebuilder *builder; const char *scan = fmt, *next; char type, delimiter; git_filemode_t mode = GIT_FILEMODE_BLOB; git_buf name = GIT_BUF_INIT; va_list arglist; cl_git_pass(git_treebuilder_new(&builder, repo, NULL)); /* start builder */ va_start(arglist, fmt); while (*scan) { switch (type = *scan++) { case 't': case 'T': mode = GIT_FILEMODE_TREE; break; case 'b': case 'B': mode = GIT_FILEMODE_BLOB; break; default: cl_assert(type == 't' || type == 'T' || type == 'b' || type == 'B'); } delimiter = *scan++; /* read and skip delimiter */ for (next = scan; *next && *next != delimiter; ++next) /* seek end */; cl_git_pass(git_buf_set(&name, scan, (size_t)(next - scan))); for (scan = next; *scan && (*scan == delimiter || *scan == ','); ++scan) /* skip delimiter and optional comma */; id = va_arg(arglist, git_oid *); cl_git_pass(git_treebuilder_insert(NULL, builder, name.ptr, id, mode)); } va_end(arglist); cl_git_pass(git_treebuilder_write(out, builder)); git_treebuilder_free(builder); git_buf_free(&name); }
/** * Reads the tree object out of a commit object, or returns an empty tree * if the commit id is zero. */ static int sync_get_tree(git_oid *out, git_repository *repo, const git_oid *commit_id) { int e = 0; git_treebuilder *tb = NULL; git_commit *commit = NULL; if (git_oid_iszero(commit_id)) { git_check(git_treebuilder_new(&tb, repo, NULL)); git_check(git_treebuilder_write(out, tb)); } else { git_check(git_commit_lookup(&commit, repo, commit_id)); git_oid_cpy(out, git_commit_tree_id(commit)); } exit: if (tb) git_treebuilder_free(tb); if (commit) git_commit_free(commit); return e; }
static int write_tree(git_oid *oid, git_index *index, const char *dirname, unsigned int start) { git_treebuilder *bld = NULL; unsigned int i, entries = git_index_entrycount(index); int error; size_t dirname_len = strlen(dirname); const git_tree_cache *cache; cache = git_tree_cache_get(index->tree, dirname); if (cache != NULL && cache->entries >= 0){ git_oid_cpy(oid, &cache->oid); return find_next_dir(dirname, index, start); } error = git_treebuilder_create(&bld, NULL); if (bld == NULL) { return GIT_ENOMEM; } /* * This loop is unfortunate, but necessary. The index doesn't have * any directores, so we need to handle that manually, and we * need to keep track of the current position. */ for (i = start; i < entries; ++i) { git_index_entry *entry = git_index_get(index, i); char *filename, *next_slash; /* * If we've left our (sub)tree, exit the loop and return. The * first check is an early out (and security for the * third). The second check is a simple prefix comparison. The * third check catches situations where there is a directory * win32/sys and a file win32mmap.c. Without it, the following * code believes there is a file win32/mmap.c */ if (strlen(entry->path) < dirname_len || memcmp(entry->path, dirname, dirname_len) || (dirname_len > 0 && entry->path[dirname_len] != '/')) { break; } filename = entry->path + dirname_len; if (*filename == '/') filename++; next_slash = strchr(filename, '/'); if (next_slash) { git_oid sub_oid; int written; char *subdir, *last_comp; subdir = git__strndup(entry->path, next_slash - entry->path); if (subdir == NULL) { error = GIT_ENOMEM; goto cleanup; } /* Write out the subtree */ written = write_tree(&sub_oid, index, subdir, i); if (written < 0) { error = git__rethrow(written, "Failed to write subtree %s", subdir); } else { i = written - 1; /* -1 because of the loop increment */ } /* * We need to figure out what we want toinsert * into this tree. If we're traversing * deps/zlib/, then we only want to write * 'zlib' into the tree. */ last_comp = strrchr(subdir, '/'); if (last_comp) { last_comp++; /* Get rid of the '/' */ } else { last_comp = subdir; } error = append_entry(bld, last_comp, &sub_oid, S_IFDIR); free(subdir); if (error < GIT_SUCCESS) { error = git__rethrow(error, "Failed to insert dir"); goto cleanup; } } else { error = append_entry(bld, filename, &entry->oid, entry->mode); if (error < GIT_SUCCESS) { error = git__rethrow(error, "Failed to insert file"); } } } error = git_treebuilder_write(oid, index->repository, bld); if (error < GIT_SUCCESS) error = git__rethrow(error, "Failed to write tree to db"); cleanup: git_treebuilder_free(bld); if (error < GIT_SUCCESS) return error; else return i; }
/** * Merges two tree objects, producing a third tree. * The base tree allows the algorithm to distinguish between adds and deletes. * The algorithm always prefers the item from tree 1 when there is a conflict. */ static int sync_merge_trees(git_oid *out, git_repository *repo, const git_oid *base_id, const git_oid *id1, const git_oid *id2) { int e = 0; git_tree *base_tree = NULL; git_tree *tree1 = NULL; git_tree *tree2 = NULL; git_treebuilder *tb = NULL; size_t size1, size2; size_t i1 = 0; size_t i2 = 0; const git_tree_entry *e1 = NULL; const git_tree_entry *e2 = NULL; enum { ONLY1 = 1, ONLY2 = 2, BOTH = 3 } state = BOTH; git_check(git_tree_lookup(&base_tree, repo, base_id)); git_check(git_tree_lookup(&tree1, repo, id1)); git_check(git_tree_lookup(&tree2, repo, id2)); git_check(git_treebuilder_new(&tb, repo, NULL)); size1 = git_tree_entrycount(tree1); size2 = git_tree_entrycount(tree2); while (1) { // Advance to next file: if (state == ONLY1 || state == BOTH) { e1 = i1 < size1 ? git_tree_entry_byindex(tree1, i1++) : NULL; } if (state == ONLY2 || state == BOTH) { e2 = i2 < size2 ? git_tree_entry_byindex(tree2, i2++) : NULL; } // Determine state: if (e1 && e2) { int s = strcmp(git_tree_entry_name(e1), git_tree_entry_name(e2)); state = s < 0 ? ONLY1 : s > 0 ? ONLY2 : BOTH; } else if (e1 && !e2) { state = ONLY1; } else if (!e1 && e2) { state = ONLY2; } else { break; } // Grab the entry in question: const git_tree_entry *entry = (state == ONLY1 || state == BOTH) ? e1 : e2; const git_tree_entry *base_entry = git_tree_entry_byname(base_tree, git_tree_entry_name(entry)); // Decide what to do with the entry: if (state == BOTH && base_entry && GIT_OBJ_TREE == git_tree_entry_type(e1) && GIT_OBJ_TREE == git_tree_entry_type(e2) && GIT_OBJ_TREE == git_tree_entry_type(base_entry)) { // Merge sub-trees: git_oid new_tree; git_check(sync_merge_trees(&new_tree, repo, git_tree_entry_id(base_entry), git_tree_entry_id(e1), git_tree_entry_id(e2))); git_check(git_treebuilder_insert(NULL, tb, git_tree_entry_name(e1), &new_tree, git_tree_entry_filemode(e1))); } else if (state == BOTH && base_entry) { if (git_oid_cmp(git_tree_entry_id(base_entry), git_tree_entry_id(e1))) { // Entry `e1` has changes, so use that: git_check(git_treebuilder_insert(NULL, tb, git_tree_entry_name(e1), git_tree_entry_id(e1), git_tree_entry_filemode(e1))); } else { // Entry `e1` has no changes, so use `e2`: git_check(git_treebuilder_insert(NULL, tb, git_tree_entry_name(e2), git_tree_entry_id(e2), git_tree_entry_filemode(e2))); } } else if (state == BOTH || !base_entry) { // Entry was added, or already present: git_check(git_treebuilder_insert(NULL, tb, git_tree_entry_name(entry), git_tree_entry_id(entry), git_tree_entry_filemode(entry))); } // Otherwise, the entry was deleted. } // Write tree: git_check(git_treebuilder_write(out, tb)); exit: if (base_tree) git_tree_free(base_tree); if (tree1) git_tree_free(tree1); if (tree2) git_tree_free(tree2); if (tb) git_treebuilder_free(tb); return e; }
int luagi_tree_builder_gc( lua_State *L ) { git_treebuilder** builder = checktreebuilder( L ); git_treebuilder_free( *builder ); return 0; }
static void rb_git_treebuilder_free(git_treebuilder *bld) { git_treebuilder_free(bld); }
/* * And the Lord said: Is this tree properly sorted? */ void test_object_tree_write__sorted_subtrees(void) { git_treebuilder *builder; unsigned int i; int position_c = -1, position_cake = -1, position_config = -1; struct { unsigned int attr; const char *filename; } entries[] = { { 0100644, ".gitattributes" }, { 0100644, ".gitignore" }, { 0100644, ".htaccess" }, { 0100644, "Capfile" }, { 0100644, "Makefile"}, { 0100644, "README"}, { 0040000, "app"}, { 0040000, "cake"}, { 0040000, "config"}, { 0100644, "c"}, { 0100644, "git_test.txt"}, { 0100644, "htaccess.htaccess"}, { 0100644, "index.php"}, { 0040000, "plugins"}, { 0040000, "schemas"}, { 0040000, "ssl-certs"}, { 0040000, "vendors"} }; git_oid blank_oid, tree_oid; memset(&blank_oid, 0x0, sizeof(blank_oid)); cl_git_pass(git_treebuilder_create(&builder, NULL)); for (i = 0; i < ARRAY_SIZE(entries); ++i) { cl_git_pass(git_treebuilder_insert(NULL, builder, entries[i].filename, &blank_oid, entries[i].attr)); } cl_git_pass(git_treebuilder_write(&tree_oid, g_repo, builder)); for (i = 0; i < builder->entries.length; ++i) { git_tree_entry *entry = git_vector_get(&builder->entries, i); if (strcmp(entry->filename, "c") == 0) position_c = i; if (strcmp(entry->filename, "cake") == 0) position_cake = i; if (strcmp(entry->filename, "config") == 0) position_config = i; } cl_assert(position_c != -1); cl_assert(position_cake != -1); cl_assert(position_config != -1); cl_assert(position_c < position_cake); cl_assert(position_cake < position_config); git_treebuilder_free(builder); }
int configctl_git_commit(char *path) { int rc; int git_status = -1; git_oid oid_blob; git_oid oid_tree; git_oid oid_commit; git_blob *blob; git_tree *tree_cmt; git_treebuilder *tree_bld; char *file; file = get_file(path); #if 0 // TODO: check if file is changed __debug("%s", file); git_diff_stats *stats; git_diff *diff; git_diff_options opts = GIT_DIFF_OPTIONS_INIT; opts.pathspec.strings = &file; opts.pathspec.count = 1; rc = git_diff_index_to_workdir(&diff, repo, NULL, &opts); if(rc) goto error; int diff_num = git_diff_num_deltas(diff); __debug("%d", diff_num); git_diff_get_stats(&stats, diff); int x = git_diff_stats_files_changed(stats); __debug("%d", x); git_diff_free(diff); #endif rc = git_add(file); if (rc) goto error; rc = git_blob_create_fromworkdir(&oid_blob, repo, file); if (rc) goto error; rc = git_blob_lookup(&blob, repo, &oid_blob); if (rc) goto error; rc = git_treebuilder_new(&tree_bld, repo, NULL ); if (0 == rc) { rc = git_treebuilder_insert(NULL, tree_bld, file, &oid_blob, GIT_FILEMODE_BLOB); if (!rc) { rc = git_treebuilder_write(&oid_tree, tree_bld); if (!rc) { rc = git_tree_lookup(&tree_cmt, repo, &oid_tree); if (0 == rc) { git_commit *commit; commit = get_last_commit(); git_signature_now(&sign, sign_name, sign_email); rc = git_commit_create(&oid_commit, repo, "HEAD", sign, sign, NULL, commit_message, tree_cmt, 1, (const struct git_commit **) &commit); if (!rc) { git_status = 0; __debug("successful git commit"); } git_tree_free( tree_cmt ); git_commit_free(commit); git_signature_free(sign); } } } git_treebuilder_free(tree_bld); } git_blob_free( blob ); error: return git_status; }
/* * And the Lord said: Is this tree properly sorted? */ void test_object_tree_write__sorted_subtrees(void) { git_treebuilder *builder; git_tree *tree; unsigned int i; int position_c = -1, position_cake = -1, position_config = -1; struct { unsigned int attr; const char *filename; } entries[] = { { GIT_FILEMODE_BLOB, ".gitattributes" }, { GIT_FILEMODE_BLOB, ".gitignore" }, { GIT_FILEMODE_BLOB, ".htaccess" }, { GIT_FILEMODE_BLOB, "Capfile" }, { GIT_FILEMODE_BLOB, "Makefile"}, { GIT_FILEMODE_BLOB, "README"}, { GIT_FILEMODE_TREE, "app"}, { GIT_FILEMODE_TREE, "cake"}, { GIT_FILEMODE_TREE, "config"}, { GIT_FILEMODE_BLOB, "c"}, { GIT_FILEMODE_BLOB, "git_test.txt"}, { GIT_FILEMODE_BLOB, "htaccess.htaccess"}, { GIT_FILEMODE_BLOB, "index.php"}, { GIT_FILEMODE_TREE, "plugins"}, { GIT_FILEMODE_TREE, "schemas"}, { GIT_FILEMODE_TREE, "ssl-certs"}, { GIT_FILEMODE_TREE, "vendors"} }; git_oid bid, tid, tree_oid; cl_git_pass(git_oid_fromstr(&bid, blob_oid)); cl_git_pass(git_oid_fromstr(&tid, first_tree)); cl_git_pass(git_treebuilder_new(&builder, g_repo, NULL)); for (i = 0; i < ARRAY_SIZE(entries); ++i) { git_oid *id = entries[i].attr == GIT_FILEMODE_TREE ? &tid : &bid; cl_git_pass(git_treebuilder_insert(NULL, builder, entries[i].filename, id, entries[i].attr)); } cl_git_pass(git_treebuilder_write(&tree_oid, builder)); cl_git_pass(git_tree_lookup(&tree, g_repo, &tree_oid)); for (i = 0; i < git_tree_entrycount(tree); i++) { const git_tree_entry *entry = git_tree_entry_byindex(tree, i); if (strcmp(entry->filename, "c") == 0) position_c = i; if (strcmp(entry->filename, "cake") == 0) position_cake = i; if (strcmp(entry->filename, "config") == 0) position_config = i; } git_tree_free(tree); cl_assert(position_c != -1); cl_assert(position_cake != -1); cl_assert(position_config != -1); cl_assert(position_c < position_cake); cl_assert(position_cake < position_config); git_treebuilder_free(builder); }
void test_object_tree_write__removing_and_re_adding_in_treebuilder(void) { git_treebuilder *builder; int i, aardvark_i, apple_i, apple_after_i, apple_extra_i, last_i; git_oid entry_oid, tree_oid; git_tree *tree; cl_git_pass(git_oid_fromstr(&entry_oid, blob_oid)); cl_git_pass(git_treebuilder_new(&builder, g_repo, NULL)); cl_assert_equal_i(0, (int)git_treebuilder_entrycount(builder)); for (i = 0; _entries[i].filename; ++i) cl_git_pass(git_treebuilder_insert(NULL, builder, _entries[i].filename, &entry_oid, _entries[i].attr)); cl_assert_equal_i(6, (int)git_treebuilder_entrycount(builder)); cl_git_pass(git_treebuilder_remove(builder, "apple")); cl_assert_equal_i(5, (int)git_treebuilder_entrycount(builder)); cl_git_pass(git_treebuilder_remove(builder, "apple_after")); cl_assert_equal_i(4, (int)git_treebuilder_entrycount(builder)); cl_git_pass(git_treebuilder_insert( NULL, builder, "before_last", &entry_oid, GIT_FILEMODE_BLOB)); cl_assert_equal_i(5, (int)git_treebuilder_entrycount(builder)); /* reinsert apple_after */ cl_git_pass(git_treebuilder_insert( NULL, builder, "apple_after", &entry_oid, GIT_FILEMODE_BLOB)); cl_assert_equal_i(6, (int)git_treebuilder_entrycount(builder)); cl_git_pass(git_treebuilder_remove(builder, "last")); cl_assert_equal_i(5, (int)git_treebuilder_entrycount(builder)); /* reinsert last */ cl_git_pass(git_treebuilder_insert( NULL, builder, "last", &entry_oid, GIT_FILEMODE_BLOB)); cl_assert_equal_i(6, (int)git_treebuilder_entrycount(builder)); cl_git_pass(git_treebuilder_insert( NULL, builder, "apple_extra", &entry_oid, GIT_FILEMODE_BLOB)); cl_assert_equal_i(7, (int)git_treebuilder_entrycount(builder)); cl_git_pass(git_treebuilder_write(&tree_oid, builder)); git_treebuilder_free(builder); cl_git_pass(git_tree_lookup(&tree, g_repo, &tree_oid)); cl_assert_equal_i(7, (int)git_tree_entrycount(tree)); cl_assert(git_tree_entry_byname(tree, ".first") != NULL); cl_assert(git_tree_entry_byname(tree, "apple") == NULL); cl_assert(git_tree_entry_byname(tree, "apple_after") != NULL); cl_assert(git_tree_entry_byname(tree, "apple_extra") != NULL); cl_assert(git_tree_entry_byname(tree, "last") != NULL); aardvark_i = apple_i = apple_after_i = apple_extra_i = last_i = -1; for (i = 0; i < 7; ++i) { const git_tree_entry *entry = git_tree_entry_byindex(tree, i); if (!strcmp(entry->filename, "aardvark")) aardvark_i = i; else if (!strcmp(entry->filename, "apple")) apple_i = i; else if (!strcmp(entry->filename, "apple_after")) apple_after_i = i; else if (!strcmp(entry->filename, "apple_extra")) apple_extra_i = i; else if (!strcmp(entry->filename, "last")) last_i = i; } cl_assert_equal_i(-1, apple_i); cl_assert_equal_i(6, last_i); cl_assert(aardvark_i < apple_after_i); cl_assert(apple_after_i < apple_extra_i); 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_new(&builder, g_repo, 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, 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_new(&builder, g_repo, 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, 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); }