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); }
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; }
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); }
PyObject * Repository_TreeBuilder(Repository *self, PyObject *args) { TreeBuilder *builder; git_treebuilder *bld; PyObject *py_src = NULL; git_oid oid; git_tree *tree = NULL; git_tree *must_free = NULL; int err; if (!PyArg_ParseTuple(args, "|O", &py_src)) return NULL; if (py_src) { if (PyObject_TypeCheck(py_src, &TreeType)) { Tree *py_tree = (Tree *)py_src; if (py_tree->repo->repo != self->repo) { //return Error_set(GIT_EINVALIDARGS); return Error_set(GIT_ERROR); } tree = py_tree->tree; } else { err = py_str_to_git_oid_expand(self->repo, py_src, &oid); if (err < 0) return NULL; err = git_tree_lookup(&tree, self->repo, &oid); if (err < 0) return Error_set(err); must_free = tree; } } err = git_treebuilder_create(&bld, tree); if (must_free != NULL) { git_tree_free(must_free); } if (err < 0) return Error_set(err); builder = PyObject_New(TreeBuilder, &TreeBuilderType); if (builder) { builder->repo = self; builder->bld = bld; Py_INCREF(self); } return (PyObject*)builder; }
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 blank_oid, tree_oid; git_tree *tree; memset(&blank_oid, 0x0, sizeof(blank_oid)); cl_git_pass(git_treebuilder_create(&builder, NULL)); for (i = 0; _entries[i].filename; ++i) cl_git_pass(git_treebuilder_insert(NULL, builder, _entries[i].filename, &blank_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, g_repo, 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 VALUE rb_git_treebuilder_init(int argc, VALUE *argv, VALUE self) { git_treebuilder *builder; git_tree *tree = NULL; VALUE rb_object; int error; if (rb_scan_args(argc, argv, "01", &rb_object) == 1) { if (!rb_obj_is_kind_of(rb_object, rb_cRuggedTree)) rb_raise(rb_eTypeError, "A Rugged::Tree instance is required"); Data_Get_Struct(rb_object, git_tree, tree); } error = git_treebuilder_create(&builder, tree); rugged_exception_check(error); DATA_PTR(self) = builder; return Qnil; }
/* * This does *not* make sure the new subdirectory doesn't * alias some existing name. That is actually useful: you * can create multiple directories with the same name, and * set the "unique" flag, which will then append the SHA1 * of the directory to the name when it is written. */ static struct dir *new_directory(struct dir *parent, struct membuffer *namebuf) { struct dir *subdir; const char *name = mb_cstring(namebuf); int len = namebuf->len; subdir = malloc(sizeof(*subdir)+len); /* * It starts out empty: no subdirectories of its own, * and an empty treebuilder list of files. */ subdir->subdirs = NULL; git_treebuilder_create(&subdir->files, NULL); memcpy(subdir->name, name, len); subdir->unique = 0; subdir->name[len] = 0; /* Add it to the list of subdirs of the parent */ subdir->sibling = parent->subdirs; parent->subdirs = subdir; return subdir; }
/* * 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 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)); 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); }
int edit_repo(const char *repo_name) { int r; git_repository *repo; git_oid blob_id; git_oid oid; git_oid tree_id; git_signature *author; git_time_t time; git_config *config; git_index *index; git_tree *tree; git_treebuilder *tree_builder; git_treebuilder *empty_tree_builder; git_reference *head; git_commit *commit_parents[1]; char global_config_path[GIT_PATH_MAX]; char out[41]; out[40] = '\0'; // create the repository r = git_repository_open(&repo, repo_name); if (r) printf("error in opening repository\n"); printf("Repo opened\n"); // create a treebuilder r = git_treebuilder_create(&tree_builder, NULL); if (r) printf("error in creting treebuilder\n"); printf("Tree builder created\n"); // ADDING FIRST FILE // create a blob r = git_blob_create_fromdisk(&blob_id, repo, "test2"); if (r) printf("error in creating blob from disk\n"); printf("Blob created\n"); // insert into tree r = git_treebuilder_insert(NULL, tree_builder, "test1", &blob_id, 0100644); if (r) printf("error in inserting into treebuilder\n"); printf("Insert into treebuilder successful\n"); // write the tree to the repo r = git_treebuilder_write(&oid, repo, tree_builder); if (r) printf("error in writing the tree to the repo\n"); printf("Writing the tree to repo successful\n"); // tree lookup r = git_tree_lookup(&tree, repo, &oid); if (r) printf("error in tree lookup\n"); printf("Tree lookup done\n"); // create a author time = get_time(); r = git_signature_new(&author, "Varun Agrawal", "*****@*****.**", time, -300); if (r) printf("error in creating signature\n"); printf("Author signature created\n"); // obtaining the head r = git_repository_head(&head, repo); if (r) printf("error in obtaining the head\n"); r = git_reference_name_to_oid(&oid, repo, git_reference_name(head)); if (r) printf("error in obtaining the ref id of head\n"); printf("Obtained the head id %s\n", git_oid_tostr(out, 41, &oid)); git_commit_lookup(&commit_parents[0], repo, &oid); // create a commit r = git_commit_create( &oid, // object id repo, // repository "HEAD", // update reference, this will update the HEAD to this commit author, // author author, // committer NULL, // message encoding, by default UTF-8 is used "second commit", // message for the commit tree, // the git_tree object which will be used as the tree for this commit. don't know if NULL is valid 1, // number of parents. Don't know what value should be used here commit_parents); // array of pointers to the parents(git_commit *parents[]) if (r) printf("error in creating a commit\n"); printf("Commit created\n"); git_repository_free(repo); return 0; }
int create_repo(const char *repo_name) { int r; git_repository *repo; git_oid blob_id; git_oid oid; git_oid tree_id; git_signature *author; git_time_t time; git_config *config; git_index *index; git_tree *tree; git_treebuilder *tree_builder; git_treebuilder *empty_tree_builder; char global_config_path[GIT_PATH_MAX]; // create the repository r = git_repository_init(&repo, repo_name, 1); if (r) printf("error in creating repository\n"); printf("Repo created\n"); // set the repository config git_config_new(&config); git_config_find_global(global_config_path, GIT_PATH_MAX); git_config_add_file_ondisk(config, global_config_path, 1); //git_config_set_string(config, "name", "Varun Agrawal"); //git_config_set_string(config, "email", "*****@*****.**"); git_repository_set_config(repo, config); printf("Repo config set\n"); // create a treebuilder r = git_treebuilder_create(&tree_builder, NULL); if (r) printf("error in creting treebuilder\n"); printf("Tree builder created\n"); // ADDING FIRST FILE // create a blob r = git_blob_create_fromdisk(&blob_id, repo, "test1"); if (r) printf("error in creating blob from disk\n"); printf("Blob created\n"); // insert into tree r = git_treebuilder_insert(NULL, tree_builder, "test1", &blob_id, 0100644); if (r) printf("error in inserting into treebuilder\n"); printf("Insert into treebuilder successful\n"); // ADDING SECOND FILE // create a blob r = git_blob_create_fromdisk(&blob_id, repo, "test2"); if (r) printf("error in creating blob from disk\n"); printf("Blob created\n"); // insert into tree r = git_treebuilder_insert(NULL, tree_builder, "test2", &blob_id, 0100644); if (r) printf("error in inserting into treebuilder\n"); printf("Insert into treebuilder successful\n"); // ADDING A EMPTY FOLDER // create a empty tree r = git_treebuilder_create(&empty_tree_builder, NULL); if (r) printf("error in creting empty treebuilder\n"); printf("Empty Tree builder created\n"); // write the empty tree to the repo r = git_treebuilder_write(&tree_id, repo, empty_tree_builder); if (r) printf("error in writing the empty tree to the repo\n"); printf("Writing the empty tree to repo successful\n"); // insert empty tree into the tree r = git_treebuilder_insert(NULL, tree_builder, "test_dir", &tree_id, 0040000); if (r) printf("error in inserting into treebuilder\n"); printf("Insert into treebuilder successful\n"); // write the tree to the repo r = git_treebuilder_write(&oid, repo, tree_builder); if (r) printf("error in writing the tree to the repo\n"); printf("Writing the tree to repo successful\n"); // tree lookup r = git_tree_lookup(&tree, repo, &oid); if (r) printf("error in tree lookup\n"); printf("Tree lookup done\n"); // create a author time = get_time(); r = git_signature_new(&author, "Varun Agrawal", "*****@*****.**", time, -300); if (r) printf("error in creating signature\n"); printf("Author signature created\n"); // create a commit r = git_commit_create( &oid, // object id repo, // repository "HEAD", // update reference, this will update the HEAD to this commit author, // author author, // committer NULL, // message encoding, by default UTF-8 is used "first commit", // message for the commit tree, // the git_tree object which will be used as the tree for this commit. don't know if NULL is valid 0, // number of parents. Don't know what value should be used here NULL); // array of pointers to the parents(git_commit *parents[]) if (r) printf("error in creating a commit\n"); printf("Commit created\n"); git_repository_free(repo); return 0; }
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); }
#endif BEGIN_TEST(write2, "write a tree from a memory") git_repository *repo; git_treebuilder *builder; git_tree *tree; git_oid id, bid, rid, id2; must_pass(open_temp_repo(&repo, REPOSITORY_FOLDER)); git_oid_mkstr(&id, first_tree); git_oid_mkstr(&id2, second_tree); git_oid_mkstr(&bid, blob_oid); //create a second tree from first tree using `git_treebuilder_insert` on REPOSITORY_FOLDER. must_pass(git_tree_lookup(&tree, repo, &id)); must_pass(git_treebuilder_create(&builder, tree)); must_pass(git_treebuilder_insert(NULL,builder,"new.txt",&bid,0100644)); must_pass(git_treebuilder_write(&rid,repo,builder)); must_be_true(git_oid_cmp(&rid, &id2) == 0); git_treebuilder_free(builder); git_tree_close(tree); close_temp_repo(repo); END_TEST BEGIN_TEST(write3, "write a hierarchical tree from a memory") git_repository *repo; git_treebuilder *builder; git_tree *tree; git_oid id, bid, subtree_id, id2, id3;
void test_core_merge__demo_create_merge_commit(void) { AGBError * error; agb_error_new(&error); // Here we're going to try to use the merge iterator to create a merge commit that contains the right information. // Note - this version does not recurse into directories. (subtrees) git_treebuilder * builder; git_treebuilder_create(&builder, base_tree); AGBMergeIterator * it = agb_merge__create_iterator(head_tree, branch_tree, base_tree, agb_merge_iterator_options_NONE); for( ; agb_merge_iterator_is_valid(it) ; agb_merge_iterator_next(it) ) { AGBMergeEntry * entry = agb_merge_entry_from_iterator(it); int hasLocalChanged = !agb_git_oid_equal( agb_merge_entry_id(entry,AGB_MERGE_BASE), agb_merge_entry_id(entry,AGB_MERGE_LOCAL) ); int hasRemoteChanged = !agb_git_oid_equal( agb_merge_entry_id(entry,AGB_MERGE_BASE), agb_merge_entry_id(entry,AGB_MERGE_REMOTE) ); printf("-- %s %d %d\n", agb_merge_entry_name(entry), hasLocalChanged, hasRemoteChanged); if( !hasLocalChanged && !hasRemoteChanged) { continue; } if( hasLocalChanged && !hasRemoteChanged) { //We want the head version. if(agb_merge_entry_id(entry,AGB_MERGE_LOCAL) == NULL) { //TODO: Check error message. printf("REMOVING %s from tree\n", agb_merge_entry_name(entry) ); git_treebuilder_remove(builder, agb_merge_entry_name(entry) ); continue; } //TODO: Check for error printf("ADDING OR UPDATING %s to tree\n", agb_merge_entry_name(entry) ); int ok = git_treebuilder_insert(NULL, builder, agb_merge_entry_name(entry), agb_merge_entry_id(entry,AGB_MERGE_LOCAL), agb_merge_entry_filemode(entry,AGB_MERGE_LOCAL) ); if(ok!=0) { printf("Error duting add/update of tree builder: %s\n", giterr_last()->message); abort(); } continue; } if( !hasLocalChanged && hasRemoteChanged) { //We want the head version. if(agb_merge_entry_id(entry,AGB_MERGE_REMOTE) == NULL) { //TODO: Check error message. printf("REMOVING %s from tree\n", agb_merge_entry_name(entry) ); git_treebuilder_remove(builder, agb_merge_entry_name(entry) ); continue; } //TODO: Check for error printf("ADDING OR UPDATING %s to tree\n", agb_merge_entry_name(entry) ); int ok = git_treebuilder_insert(NULL, builder, agb_merge_entry_name(entry), agb_merge_entry_id(entry,AGB_MERGE_REMOTE), agb_merge_entry_filemode(entry,AGB_MERGE_REMOTE) ); if(ok!=0) { printf("Error duting add/update of tree builder: %s\n", giterr_last()->message); abort(); } continue; } printf("CONFLICT %s in tree\n", agb_merge_entry_name(entry) ); //TODO: CONFLICT - Handle it! } // Our tree builder should now be full... // Lets write it out to a tree // //TODO: Check for errors git_oid new_tree_oid = {}; git_treebuilder_write(&new_tree_oid, repo, builder); char hexid[GIT_OID_HEXSZ+1]; printf("Tree SHA is %s\n", git_oid_tostr(hexid,GIT_OID_HEXSZ+1, &new_tree_oid)); git_tree * new_tree = NULL; git_tree_lookup(&new_tree, repo, &new_tree_oid); // Now we need to create the commit. const git_commit** parents = (const git_commit**)malloc(sizeof(git_commit*)*2); parents[0] = head_commit; parents[1] = branch_commit; git_signature * author_signature = NULL; // Time since epoch // TODO: Get these correctly - // Could use git_signature_now instead... { git_time_t author_time = time(NULL); int timezone_offset = 0; int ok; if((ok=git_signature_new(&author_signature,"Someone","*****@*****.**", author_time, timezone_offset))!=0) { agb__error_translate(error,"git_signature_new failed",ok); goto cleanup_error; } } git_oid commit_id; int ok = git_commit_create( &commit_id, repo, NULL, author_signature, author_signature, "UTF-8", "An exciting commit", new_tree, 2, //Two parents parents ); if(ok!=0) { agb__error_translate(error,"git_commit_create failed",ok); goto cleanup_error; } // Then update the refs. //TODO: Do we need to release this ref? git_reference * ref; ok = git_reference_create_matching( &ref, repo, "refs/heads/branch_c", &commit_id, 1, NULL, author_signature, "merged by libagb"); if(ok!=0) { agb__error_translate(error,"git_reference_create failed",ok); goto cleanup_error; } git_signature_free(author_signature); // Now check we got the expected files cl_assert_equal_c('A', test_core_merge__compare_with_parents_merge_base("branch_c", "created_in_a.txt")); cl_assert_equal_c('A', test_core_merge__compare_with_parents_merge_base("branch_c", "created_in_b.txt")); return; cleanup_error: printf("ERROR: %s\n",error->message); if(author_signature) { git_signature_free(author_signature); } cl_fail(error->message); }
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; }
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 blank_oid, tree_oid; git_tree *tree; memset(&blank_oid, 0x0, sizeof(blank_oid)); cl_git_pass(git_treebuilder_create(&builder, 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, &blank_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", &blank_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", &blank_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", &blank_oid, GIT_FILEMODE_BLOB)); cl_assert_equal_i(6, (int)git_treebuilder_entrycount(builder)); cl_git_pass(git_treebuilder_insert( NULL, builder, "apple_extra", &blank_oid, GIT_FILEMODE_BLOB)); cl_assert_equal_i(7, (int)git_treebuilder_entrycount(builder)); cl_git_pass(git_treebuilder_write(&tree_oid, g_repo, 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); }