bool next_tree_internal(Tree* t) { Tree *son, *sib; if ((son = t->son) && next_tree_internal(son)) return true; if ((sib = t->sib) && next_tree_internal(sib)) { if (son) reset_tree(son); return true; } if (son) { reset_tree(son); Tree* tmp = son; t->son = tmp->son; tmp->son = 0; if (!sib) t->sib = tmp; else { reset_tree(sib); tmp->son = sib; t->sib = tmp; } return true; } else return false; }
/* * reset t to a single path, actually it's DFS sequence path */ void reset_tree(Tree* t) { Tree *son, *sib; if ((son = t->son)) reset_tree(son); if ((sib = t->sib)) reset_tree(sib); while (t->son) t = t->son; t->son = sib; t->sib = 0; }
int copy(struct tree *dst, struct tree *src) { error::set_num_pos(error::empty_expression, 0); reset_tree(dst); dst->root = copy_branch(dst, src->root); return 0 != dst->root; }
static int stash_working_tree(struct stash_info *info, struct pathspec ps) { int ret = 0; struct rev_info rev; struct child_process cp_upd_index = CHILD_PROCESS_INIT; struct strbuf diff_output = STRBUF_INIT; struct index_state istate = { NULL }; init_revisions(&rev, NULL); set_alternate_index_output(stash_index_path.buf); if (reset_tree(&info->i_tree, 0, 0)) { ret = -1; goto done; } set_alternate_index_output(NULL); rev.prune_data = ps; rev.diffopt.output_format = DIFF_FORMAT_CALLBACK; rev.diffopt.format_callback = add_diff_to_buf; rev.diffopt.format_callback_data = &diff_output; if (read_cache_preload(&rev.diffopt.pathspec) < 0) { ret = -1; goto done; } add_pending_object(&rev, parse_object(the_repository, &info->b_commit), ""); if (run_diff_index(&rev, 0)) { ret = -1; goto done; } cp_upd_index.git_cmd = 1; argv_array_pushl(&cp_upd_index.args, "update-index", "-z", "--add", "--remove", "--stdin", NULL); argv_array_pushf(&cp_upd_index.env_array, "GIT_INDEX_FILE=%s", stash_index_path.buf); if (pipe_command(&cp_upd_index, diff_output.buf, diff_output.len, NULL, 0, NULL, 0)) { ret = -1; goto done; } if (write_index_as_tree(&info->w_tree, &istate, stash_index_path.buf, 0, NULL)) { ret = -1; goto done; } done: discard_index(&istate); UNLEAK(rev); object_array_clear(&rev.pending); strbuf_release(&diff_output); remove_path(stash_index_path.buf); return ret; }
/** * total_branch_length - calculate the total branch length. * * As each node has recorded a coalescent event at the *total* time * point, we need to add the *differences* in time between node and * its parent * * @param n - Node * * @return double - total branch length */ double total_branch_length(struct Node *n) { double tbl = 0.0; reset_tree(n); while (n != NULL) { if (n != NULL) { if (!n->visited && n->parent != NULL) { n->visited = TRUE; tbl += n->parent->time - n->time; } } n = visit_node(n); } return tbl; }
/** * segregating_sites - calculate the number of segregating sites * * @param n - Node * * @return int - the number of segregating sites */ int segregating_sites(struct Node *n) { int sites = 0; reset_tree(n); while (n != NULL) { if (n != NULL) { if (!n->visited) { n->visited = TRUE; sites += n->mutations; } } n = visit_node(n); } return sites; }
static int do_apply_stash(const char *prefix, struct stash_info *info, int index, int quiet) { int ret; int has_index = index; struct merge_options o; struct object_id c_tree; struct object_id index_tree; struct commit *result; const struct object_id *bases[1]; read_cache_preload(NULL); if (refresh_cache(REFRESH_QUIET)) return -1; if (write_cache_as_tree(&c_tree, 0, NULL)) return error(_("cannot apply a stash in the middle of a merge")); if (index) { if (oideq(&info->b_tree, &info->i_tree) || oideq(&c_tree, &info->i_tree)) { has_index = 0; } else { struct strbuf out = STRBUF_INIT; if (diff_tree_binary(&out, &info->w_commit)) { strbuf_release(&out); return error(_("could not generate diff %s^!."), oid_to_hex(&info->w_commit)); } ret = apply_cached(&out); strbuf_release(&out); if (ret) return error(_("conflicts in index." "Try without --index.")); discard_cache(); read_cache(); if (write_cache_as_tree(&index_tree, 0, NULL)) return error(_("could not save index tree")); reset_head(); } } if (info->has_u && restore_untracked(&info->u_tree)) return error(_("could not restore untracked files from stash")); init_merge_options(&o, the_repository); o.branch1 = "Updated upstream"; o.branch2 = "Stashed changes"; if (oideq(&info->b_tree, &c_tree)) o.branch1 = "Version stash was based on"; if (quiet) o.verbosity = 0; if (o.verbosity >= 3) printf_ln(_("Merging %s with %s"), o.branch1, o.branch2); bases[0] = &info->b_tree; ret = merge_recursive_generic(&o, &c_tree, &info->w_tree, 1, bases, &result); if (ret) { rerere(0); if (index) fprintf_ln(stderr, _("Index was not unstashed.")); return ret; } if (has_index) { if (reset_tree(&index_tree, 0, 0)) return -1; } else { struct strbuf out = STRBUF_INIT; if (get_newly_staged(&out, &c_tree)) { strbuf_release(&out); return -1; } if (reset_tree(&c_tree, 0, 1)) { strbuf_release(&out); return -1; } ret = update_index(&out); strbuf_release(&out); if (ret) return -1; discard_cache(); } if (quiet) { if (refresh_cache(REFRESH_QUIET)) warning("could not refresh index"); } else { struct child_process cp = CHILD_PROCESS_INIT; /* * Status is quite simple and could be replaced with calls to * wt_status in the future, but it adds complexities which may * require more tests. */ cp.git_cmd = 1; cp.dir = prefix; argv_array_push(&cp.args, "status"); run_command(&cp); } return 0; }
static int do_push_stash(struct pathspec ps, const char *stash_msg, int quiet, int keep_index, int patch_mode, int include_untracked) { int ret = 0; struct stash_info info; struct strbuf patch = STRBUF_INIT; struct strbuf stash_msg_buf = STRBUF_INIT; struct strbuf untracked_files = STRBUF_INIT; if (patch_mode && keep_index == -1) keep_index = 1; if (patch_mode && include_untracked) { fprintf_ln(stderr, _("Can't use --patch and --include-untracked" " or --all at the same time")); ret = -1; goto done; } read_cache_preload(NULL); if (!include_untracked && ps.nr) { int i; char *ps_matched = xcalloc(ps.nr, 1); for (i = 0; i < active_nr; i++) ce_path_match(&the_index, active_cache[i], &ps, ps_matched); if (report_path_error(ps_matched, &ps, NULL)) { fprintf_ln(stderr, _("Did you forget to 'git add'?")); ret = -1; free(ps_matched); goto done; } free(ps_matched); } if (refresh_cache(REFRESH_QUIET)) { ret = -1; goto done; } if (!check_changes(ps, include_untracked, &untracked_files)) { if (!quiet) printf_ln(_("No local changes to save")); goto done; } if (!reflog_exists(ref_stash) && do_clear_stash()) { ret = -1; if (!quiet) fprintf_ln(stderr, _("Cannot initialize stash")); goto done; } if (stash_msg) strbuf_addstr(&stash_msg_buf, stash_msg); if (do_create_stash(ps, &stash_msg_buf, include_untracked, patch_mode, &info, &patch, quiet)) { ret = -1; goto done; } if (do_store_stash(&info.w_commit, stash_msg_buf.buf, 1)) { ret = -1; if (!quiet) fprintf_ln(stderr, _("Cannot save the current status")); goto done; } if (!quiet) printf_ln(_("Saved working directory and index state %s"), stash_msg_buf.buf); if (!patch_mode) { if (include_untracked && !ps.nr) { struct child_process cp = CHILD_PROCESS_INIT; cp.git_cmd = 1; argv_array_pushl(&cp.args, "clean", "--force", "--quiet", "-d", NULL); if (include_untracked == INCLUDE_ALL_FILES) argv_array_push(&cp.args, "-x"); if (run_command(&cp)) { ret = -1; goto done; } } discard_cache(); if (ps.nr) { struct child_process cp_add = CHILD_PROCESS_INIT; struct child_process cp_diff = CHILD_PROCESS_INIT; struct child_process cp_apply = CHILD_PROCESS_INIT; struct strbuf out = STRBUF_INIT; cp_add.git_cmd = 1; argv_array_push(&cp_add.args, "add"); if (!include_untracked) argv_array_push(&cp_add.args, "-u"); if (include_untracked == INCLUDE_ALL_FILES) argv_array_push(&cp_add.args, "--force"); argv_array_push(&cp_add.args, "--"); add_pathspecs(&cp_add.args, ps); if (run_command(&cp_add)) { ret = -1; goto done; } cp_diff.git_cmd = 1; argv_array_pushl(&cp_diff.args, "diff-index", "-p", "--cached", "--binary", "HEAD", "--", NULL); add_pathspecs(&cp_diff.args, ps); if (pipe_command(&cp_diff, NULL, 0, &out, 0, NULL, 0)) { ret = -1; goto done; } cp_apply.git_cmd = 1; argv_array_pushl(&cp_apply.args, "apply", "--index", "-R", NULL); if (pipe_command(&cp_apply, out.buf, out.len, NULL, 0, NULL, 0)) { ret = -1; goto done; } } else { struct child_process cp = CHILD_PROCESS_INIT; cp.git_cmd = 1; argv_array_pushl(&cp.args, "reset", "--hard", "-q", NULL); if (run_command(&cp)) { ret = -1; goto done; } } if (keep_index == 1 && !is_null_oid(&info.i_tree)) { struct child_process cp_ls = CHILD_PROCESS_INIT; struct child_process cp_checkout = CHILD_PROCESS_INIT; struct strbuf out = STRBUF_INIT; if (reset_tree(&info.i_tree, 0, 1)) { ret = -1; goto done; } cp_ls.git_cmd = 1; argv_array_pushl(&cp_ls.args, "ls-files", "-z", "--modified", "--", NULL); add_pathspecs(&cp_ls.args, ps); if (pipe_command(&cp_ls, NULL, 0, &out, 0, NULL, 0)) { ret = -1; goto done; } cp_checkout.git_cmd = 1; argv_array_pushl(&cp_checkout.args, "checkout-index", "-z", "--force", "--stdin", NULL); if (pipe_command(&cp_checkout, out.buf, out.len, NULL, 0, NULL, 0)) { ret = -1; goto done; } } goto done; } else { struct child_process cp = CHILD_PROCESS_INIT; cp.git_cmd = 1; argv_array_pushl(&cp.args, "apply", "-R", NULL); if (pipe_command(&cp, patch.buf, patch.len, NULL, 0, NULL, 0)) { if (!quiet) fprintf_ln(stderr, _("Cannot remove " "worktree changes")); ret = -1; goto done; } if (keep_index < 1) { struct child_process cp = CHILD_PROCESS_INIT; discard_cache(); cp.git_cmd = 1; argv_array_pushl(&cp.args, "reset", "-q", "--", NULL); add_pathspecs(&cp.args, ps); if (run_command(&cp)) { ret = -1; goto done; } } goto done; } done: strbuf_release(&stash_msg_buf); return ret; }
static int merge_working_tree(const struct checkout_opts *opts, struct branch_info *old_branch_info, struct branch_info *new_branch_info, int *writeout_error) { int ret; struct lock_file lock_file = LOCK_INIT; hold_locked_index(&lock_file, LOCK_DIE_ON_ERROR); if (read_cache_preload(NULL) < 0) return error(_("index file corrupt")); resolve_undo_clear(); if (opts->force) { ret = reset_tree(get_commit_tree(new_branch_info->commit), opts, 1, writeout_error); if (ret) return ret; } else { struct tree_desc trees[2]; struct tree *tree; struct unpack_trees_options topts; memset(&topts, 0, sizeof(topts)); topts.head_idx = -1; topts.src_index = &the_index; topts.dst_index = &the_index; setup_unpack_trees_porcelain(&topts, "checkout"); refresh_cache(REFRESH_QUIET); if (unmerged_cache()) { error(_("you need to resolve your current index first")); return 1; } /* 2-way merge to the new branch */ topts.initial_checkout = is_cache_unborn(); topts.update = 1; topts.merge = 1; topts.gently = opts->merge && old_branch_info->commit; topts.verbose_update = opts->show_progress; topts.fn = twoway_merge; if (opts->overwrite_ignore) { topts.dir = xcalloc(1, sizeof(*topts.dir)); topts.dir->flags |= DIR_SHOW_IGNORED; setup_standard_excludes(topts.dir); } tree = parse_tree_indirect(old_branch_info->commit ? &old_branch_info->commit->object.oid : the_hash_algo->empty_tree); init_tree_desc(&trees[0], tree->buffer, tree->size); tree = parse_tree_indirect(&new_branch_info->commit->object.oid); init_tree_desc(&trees[1], tree->buffer, tree->size); ret = unpack_trees(2, trees, &topts); clear_unpack_trees_porcelain(&topts); if (ret == -1) { /* * Unpack couldn't do a trivial merge; either * give up or do a real merge, depending on * whether the merge flag was used. */ struct tree *result; struct tree *work; struct merge_options o; if (!opts->merge) return 1; /* * Without old_branch_info->commit, the below is the same as * the two-tree unpack we already tried and failed. */ if (!old_branch_info->commit) return 1; /* Do more real merge */ /* * We update the index fully, then write the * tree from the index, then merge the new * branch with the current tree, with the old * branch as the base. Then we reset the index * (but not the working tree) to the new * branch, leaving the working tree as the * merged version, but skipping unmerged * entries in the index. */ add_files_to_cache(NULL, NULL, 0); /* * NEEDSWORK: carrying over local changes * when branches have different end-of-line * normalization (or clean+smudge rules) is * a pain; plumb in an option to set * o.renormalize? */ init_merge_options(&o, the_repository); o.verbosity = 0; work = write_tree_from_memory(&o); ret = reset_tree(get_commit_tree(new_branch_info->commit), opts, 1, writeout_error); if (ret) return ret; o.ancestor = old_branch_info->name; o.branch1 = new_branch_info->name; o.branch2 = "local"; ret = merge_trees(&o, get_commit_tree(new_branch_info->commit), work, get_commit_tree(old_branch_info->commit), &result); if (ret < 0) exit(128); ret = reset_tree(get_commit_tree(new_branch_info->commit), opts, 0, writeout_error); strbuf_release(&o.obuf); if (ret) return ret; } } if (!active_cache_tree) active_cache_tree = cache_tree(); if (!cache_tree_fully_valid(active_cache_tree)) cache_tree_update(&the_index, WRITE_TREE_SILENT | WRITE_TREE_REPAIR); if (write_locked_index(&the_index, &lock_file, COMMIT_LOCK)) die(_("unable to write new index file")); if (!opts->force && !opts->quiet) show_local_changes(&new_branch_info->commit->object, &opts->diff_options); return 0; }
TREE_ELEMENT *tree_insert(TREE *tree, void *key, uint key_size, void* custom_arg) { int cmp; TREE_ELEMENT *element,***parent; parent= tree->parents; *parent = &tree->root; element= tree->root; for (;;) { if (element == &tree->null_element || (cmp = (*tree->compare)(custom_arg, ELEMENT_KEY(tree,element), key)) == 0) break; if (cmp < 0) { *++parent= &element->right; element= element->right; } else { *++parent = &element->left; element= element->left; } } if (element == &tree->null_element) { uint alloc_size=sizeof(TREE_ELEMENT)+key_size+tree->size_of_element; tree->allocated+=alloc_size; if (tree->memory_limit && tree->elements_in_tree && tree->allocated > tree->memory_limit) { reset_tree(tree); return tree_insert(tree, key, key_size, custom_arg); } key_size+=tree->size_of_element; if (tree->with_delete) element=(TREE_ELEMENT *) my_malloc(alloc_size, MYF(MY_WME)); else element=(TREE_ELEMENT *) alloc_root(&tree->mem_root,alloc_size); if (!element) return(NULL); **parent=element; element->left=element->right= &tree->null_element; if (!tree->offset_to_key) { if (key_size == sizeof(void*)) /* no length, save pointer */ *((void**) (element+1))=key; else { *((void**) (element+1))= (void*) ((void **) (element+1)+1); memcpy((uchar*) *((void **) (element+1)),key, (size_t) (key_size-sizeof(void*))); } } else memcpy((uchar*) element+tree->offset_to_key,key,(size_t) key_size); element->count=1; /* May give warning in purify */ tree->elements_in_tree++; rb_insert(tree,parent,element); /* rebalance tree */ } else { if (tree->flag & TREE_NO_DUPS) return(NULL); element->count++; /* Avoid a wrap over of the count. */ if (! element->count) element->count--; } DBUG_EXECUTE("check_tree", test_rb_tree(tree->root););