PyObject * Diff_find_similar(Diff *self, PyObject *args) { int err; git_diff_find_options opts = GIT_DIFF_FIND_OPTIONS_INIT; if (!PyArg_ParseTuple(args, "|i", &opts.flags)) return NULL; err = git_diff_find_similar(self->list, &opts); if (err < 0) return Error_set(err); Py_RETURN_NONE; }
static void diff_stats_from_commit_oid( git_diff_stats **stats, const char *oidstr, bool rename) { git_oid oid; git_commit *commit; git_diff *diff; git_oid_fromstr(&oid, oidstr); cl_git_pass(git_commit_lookup(&commit, _repo, &oid)); cl_git_pass(git_diff__commit(&diff, _repo, commit, NULL)); if (rename) cl_git_pass(git_diff_find_similar(diff, NULL)); cl_git_pass(git_diff_get_stats(stats, diff)); git_diff_free(diff); git_commit_free(commit); }
PyObject * Diff_find_similar(Diff *self, PyObject *args, PyObject *kwds) { int err; git_diff_find_options opts = GIT_DIFF_FIND_OPTIONS_INIT; char *keywords[] = {"flags", "rename_threshold", "copy_threshold", "rename_from_rewrite_threshold", "break_rewrite_threshold", "rename_limit", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwds, "|iHHHHI", keywords, &opts.flags, &opts.rename_threshold, &opts.copy_threshold, &opts.rename_from_rewrite_threshold, &opts.break_rewrite_threshold, &opts.rename_limit)) return NULL; err = git_diff_find_similar(self->diff, &opts); if (err < 0) return Error_set(err); Py_RETURN_NONE; }
static void test_tree_to_tree_computed_to_parsed( const char *sandbox, const char *a_id, const char *b_id, uint32_t diff_flags, uint32_t find_flags) { git_repository *repo; git_diff *computed, *parsed; git_tree *a, *b; git_diff_options opts = GIT_DIFF_OPTIONS_INIT; git_diff_find_options findopts = GIT_DIFF_FIND_OPTIONS_INIT; git_buf computed_buf = GIT_BUF_INIT; repo = cl_git_sandbox_init(sandbox); opts.id_abbrev = GIT_OID_HEXSZ; opts.flags = GIT_DIFF_SHOW_BINARY | diff_flags; findopts.flags = find_flags; cl_assert((a = resolve_commit_oid_to_tree(repo, a_id)) != NULL); cl_assert((b = resolve_commit_oid_to_tree(repo, b_id)) != NULL); cl_git_pass(git_diff_tree_to_tree(&computed, repo, a, b, &opts)); if (find_flags) cl_git_pass(git_diff_find_similar(computed, &findopts)); cl_git_pass(git_diff_to_buf(&computed_buf, computed, GIT_DIFF_FORMAT_PATCH)); cl_git_pass(git_diff_from_buffer(&parsed, computed_buf.ptr, computed_buf.size)); diff_assert_equal(computed, parsed); git_tree_free(a); git_tree_free(b); git_diff_free(computed); git_diff_free(parsed); git_buf_free(&computed_buf); cl_git_sandbox_cleanup(); }
int luagi_diff_find_similar( lua_State *L ) { git_diff **diff = checkdiff_at( L, 1 ); luaL_checktype( L, 2, LUA_TTABLE ); git_diff_find_options options; if( luagi_diff_find_init_options( L, 2, &options ) ) { const git_error *err = giterr_last(); luaL_error( L, err->message ); } if( git_diff_find_similar( *diff, &options ) ) { const git_error *err = giterr_last(); luaL_error( L, err->message ); } return 0; }
int lg2_diff(git_repository *repo, int argc, char *argv[]) { git_tree *t1 = NULL, *t2 = NULL; git_diff *diff; struct opts o = { GIT_DIFF_OPTIONS_INIT, GIT_DIFF_FIND_OPTIONS_INIT, -1, 0, 0, GIT_DIFF_FORMAT_PATCH, NULL, NULL, "." }; parse_opts(&o, argc, argv); /** * Possible argument patterns: * * * <sha1> <sha2> * * <sha1> --cached * * <sha1> * * --cached * * --nocache (don't use index data in diff at all) * * nothing * * Currently ranged arguments like <sha1>..<sha2> and <sha1>...<sha2> * are not supported in this example */ if (o.treeish1) treeish_to_tree(&t1, repo, o.treeish1); if (o.treeish2) treeish_to_tree(&t2, repo, o.treeish2); if (t1 && t2) check_lg2( git_diff_tree_to_tree(&diff, repo, t1, t2, &o.diffopts), "diff trees", NULL); else if (o.cache != CACHE_NORMAL) { if (!t1) treeish_to_tree(&t1, repo, "HEAD"); if (o.cache == CACHE_NONE) check_lg2( git_diff_tree_to_workdir(&diff, repo, t1, &o.diffopts), "diff tree to working directory", NULL); else check_lg2( git_diff_tree_to_index(&diff, repo, t1, NULL, &o.diffopts), "diff tree to index", NULL); } else if (t1) check_lg2( git_diff_tree_to_workdir_with_index(&diff, repo, t1, &o.diffopts), "diff tree to working directory", NULL); else check_lg2( git_diff_index_to_workdir(&diff, repo, NULL, &o.diffopts), "diff index to working directory", NULL); /** Apply rename and copy detection if requested. */ if ((o.findopts.flags & GIT_DIFF_FIND_ALL) != 0) check_lg2( git_diff_find_similar(diff, &o.findopts), "finding renames and copies", NULL); /** Generate simple output using libgit2 display helper. */ if (!o.output) o.output = OUTPUT_DIFF; if (o.output != OUTPUT_DIFF) diff_print_stats(diff, &o); if ((o.output & OUTPUT_DIFF) != 0) { if (o.color >= 0) fputs(colors[0], stdout); check_lg2( git_diff_print(diff, o.format, color_printer, &o.color), "displaying diff", NULL); if (o.color >= 0) fputs(colors[0], stdout); } /** Cleanup before exiting. */ git_diff_free(diff); git_tree_free(t1); git_tree_free(t2); return 0; }
static git_blame__origin* find_origin( git_blame *blame, git_commit *parent, git_blame__origin *origin) { git_blame__origin *porigin = NULL; git_diff *difflist = NULL; git_diff_options diffopts = GIT_DIFF_OPTIONS_INIT; git_tree *otree=NULL, *ptree=NULL; /* Get the trees from this commit and its parent */ if (0 != git_commit_tree(&otree, origin->commit) || 0 != git_commit_tree(&ptree, parent)) goto cleanup; /* Configure the diff */ diffopts.context_lines = 0; diffopts.flags = GIT_DIFF_SKIP_BINARY_CHECK; /* Check to see if files we're interested have changed */ diffopts.pathspec.count = blame->paths.length; diffopts.pathspec.strings = (char**)blame->paths.contents; if (0 != git_diff_tree_to_tree(&difflist, blame->repository, ptree, otree, &diffopts)) goto cleanup; if (!git_diff_num_deltas(difflist)) { /* No changes; copy data */ git_blame__get_origin(&porigin, blame, parent, origin->path); } else { git_diff_find_options findopts = GIT_DIFF_FIND_OPTIONS_INIT; int i; /* Generate a full diff between the two trees */ git_diff_free(difflist); diffopts.pathspec.count = 0; if (0 != git_diff_tree_to_tree(&difflist, blame->repository, ptree, otree, &diffopts)) goto cleanup; /* Let diff find renames */ findopts.flags = GIT_DIFF_FIND_RENAMES; if (0 != git_diff_find_similar(difflist, &findopts)) goto cleanup; /* Find one that matches */ for (i=0; i<(int)git_diff_num_deltas(difflist); i++) { const git_diff_delta *delta = git_diff_get_delta(difflist, i); if (!git_vector_bsearch(NULL, &blame->paths, delta->new_file.path)) { git_vector_insert_sorted(&blame->paths, (void*)git__strdup(delta->old_file.path), paths_on_dup); make_origin(&porigin, parent, delta->old_file.path); } } } cleanup: git_diff_free(difflist); git_tree_free(otree); git_tree_free(ptree); return porigin; }
static void test_with_many(int expected_new) { git_index *index; git_tree *tree, *new_tree; git_diff *diff = NULL; diff_expects exp; git_diff_options diffopts = GIT_DIFF_OPTIONS_INIT; git_diff_find_options opts = GIT_DIFF_FIND_OPTIONS_INIT; cl_git_pass(git_repository_index(&index, g_repo)); cl_git_pass( git_revparse_single((git_object **)&tree, g_repo, "HEAD^{tree}")); cl_git_pass(p_rename("renames/ikeepsix.txt", "renames/ikeepsix2.txt")); cl_git_pass(git_index_remove_bypath(index, "ikeepsix.txt")); cl_git_pass(git_index_add_bypath(index, "ikeepsix2.txt")); cl_git_pass(git_index_write(index)); cl_git_pass(git_diff_tree_to_index(&diff, g_repo, tree, index, &diffopts)); memset(&exp, 0, sizeof(exp)); cl_git_pass(git_diff_foreach( diff, diff_file_cb, NULL, NULL, NULL, &exp)); cl_assert_equal_i(1, exp.file_status[GIT_DELTA_DELETED]); cl_assert_equal_i(expected_new + 1, exp.file_status[GIT_DELTA_ADDED]); cl_assert_equal_i(expected_new + 2, exp.files); opts.flags = GIT_DIFF_FIND_ALL; cl_git_pass(git_diff_find_similar(diff, &opts)); memset(&exp, 0, sizeof(exp)); cl_git_pass(git_diff_foreach( diff, diff_file_cb, NULL, NULL, NULL, &exp)); cl_assert_equal_i(1, exp.file_status[GIT_DELTA_RENAMED]); cl_assert_equal_i(expected_new, exp.file_status[GIT_DELTA_ADDED]); cl_assert_equal_i(expected_new + 1, exp.files); git_diff_free(diff); cl_repo_commit_from_index(NULL, g_repo, NULL, 1372350000, "yoyoyo"); cl_git_pass(git_revparse_single( (git_object **)&new_tree, g_repo, "HEAD^{tree}")); cl_git_pass(git_diff_tree_to_tree( &diff, g_repo, tree, new_tree, &diffopts)); memset(&exp, 0, sizeof(exp)); cl_git_pass(git_diff_foreach( diff, diff_file_cb, NULL, NULL, NULL, &exp)); cl_assert_equal_i(1, exp.file_status[GIT_DELTA_DELETED]); cl_assert_equal_i(expected_new + 1, exp.file_status[GIT_DELTA_ADDED]); cl_assert_equal_i(expected_new + 2, exp.files); opts.flags = GIT_DIFF_FIND_ALL; cl_git_pass(git_diff_find_similar(diff, &opts)); memset(&exp, 0, sizeof(exp)); cl_git_pass(git_diff_foreach( diff, diff_file_cb, NULL, NULL, NULL, &exp)); cl_assert_equal_i(1, exp.file_status[GIT_DELTA_RENAMED]); cl_assert_equal_i(expected_new, exp.file_status[GIT_DELTA_ADDED]); cl_assert_equal_i(expected_new + 1, exp.files); git_diff_free(diff); git_tree_free(new_tree); git_tree_free(tree); git_index_free(index); }