diff options
Diffstat (limited to 'builtin/difftool.c')
-rw-r--r-- | builtin/difftool.c | 105 |
1 files changed, 67 insertions, 38 deletions
diff --git a/builtin/difftool.c b/builtin/difftool.c index 25e54ad3ed..8864d846f8 100644 --- a/builtin/difftool.c +++ b/builtin/difftool.c @@ -12,6 +12,7 @@ * Copyright (C) 2016 Johannes Schindelin */ #include "cache.h" +#include "config.h" #include "builtin.h" #include "run-command.h" #include "exec_cmd.h" @@ -129,9 +130,13 @@ struct working_tree_entry { char path[FLEX_ARRAY]; }; -static int working_tree_entry_cmp(struct working_tree_entry *a, - struct working_tree_entry *b, void *keydata) +static int working_tree_entry_cmp(const void *unused_cmp_data, + const void *entry, + const void *entry_or_key, + const void *unused_keydata) { + const struct working_tree_entry *a = entry; + const struct working_tree_entry *b = entry_or_key; return strcmp(a->path, b->path); } @@ -145,8 +150,14 @@ struct pair_entry { const char path[FLEX_ARRAY]; }; -static int pair_cmp(struct pair_entry *a, struct pair_entry *b, void *keydata) +static int pair_cmp(const void *unused_cmp_data, + const void *entry, + const void *entry_or_key, + const void *unused_keydata) { + const struct pair_entry *a = entry; + const struct pair_entry *b = entry_or_key; + return strcmp(a->path, b->path); } @@ -173,8 +184,14 @@ struct path_entry { char path[FLEX_ARRAY]; }; -static int path_entry_cmp(struct path_entry *a, struct path_entry *b, void *key) +static int path_entry_cmp(const void *unused_cmp_data, + const void *entry, + const void *entry_or_key, + const void *key) { + const struct path_entry *a = entry; + const struct path_entry *b = entry_or_key; + return strcmp(a->path, key ? key : b->path); } @@ -226,6 +243,7 @@ static void changed_files(struct hashmap *result, const char *index_path, hashmap_entry_init(entry, strhash(buf.buf)); hashmap_add(result, entry); } + fclose(fp); if (finish_command(&diff_files)) die("diff-files did not exit properly"); strbuf_release(&index_env); @@ -297,6 +315,19 @@ static char *get_symlink(const struct object_id *oid, const char *path) return data; } +static int checkout_path(unsigned mode, struct object_id *oid, + const char *path, const struct checkout *state) +{ + struct cache_entry *ce; + int ret; + + ce = make_cache_entry(mode, oid->hash, path, 0, 0); + ret = checkout_entry(ce, state, NULL); + + free(ce); + return ret; +} + static int run_dir_diff(const char *extcmd, int symlinks, const char *prefix, int argc, const char **argv) { @@ -305,8 +336,8 @@ static int run_dir_diff(const char *extcmd, int symlinks, const char *prefix, struct strbuf rpath = STRBUF_INIT, buf = STRBUF_INIT; struct strbuf ldir = STRBUF_INIT, rdir = STRBUF_INIT; struct strbuf wtdir = STRBUF_INIT; + char *lbase_dir, *rbase_dir; size_t ldir_len, rdir_len, wtdir_len; - struct cache_entry *ce = xcalloc(1, sizeof(ce) + PATH_MAX + 1); const char *workdir, *tmp; int ret = 0, i; FILE *fp; @@ -339,11 +370,11 @@ static int run_dir_diff(const char *extcmd, int symlinks, const char *prefix, memset(&wtindex, 0, sizeof(wtindex)); memset(&lstate, 0, sizeof(lstate)); - lstate.base_dir = ldir.buf; + lstate.base_dir = lbase_dir = xstrdup(ldir.buf); lstate.base_dir_len = ldir.len; lstate.force = 1; memset(&rstate, 0, sizeof(rstate)); - rstate.base_dir = rdir.buf; + rstate.base_dir = rbase_dir = xstrdup(rdir.buf); rstate.base_dir_len = rdir.len; rstate.force = 1; @@ -351,10 +382,9 @@ static int run_dir_diff(const char *extcmd, int symlinks, const char *prefix, rdir_len = rdir.len; wtdir_len = wtdir.len; - hashmap_init(&working_tree_dups, - (hashmap_cmp_fn)working_tree_entry_cmp, 0); - hashmap_init(&submodules, (hashmap_cmp_fn)pair_cmp, 0); - hashmap_init(&symlinks2, (hashmap_cmp_fn)pair_cmp, 0); + hashmap_init(&working_tree_dups, working_tree_entry_cmp, NULL, 0); + hashmap_init(&submodules, pair_cmp, NULL, 0); + hashmap_init(&symlinks2, pair_cmp, NULL, 0); child.no_stdin = 1; child.git_cmd = 1; @@ -377,7 +407,6 @@ static int run_dir_diff(const char *extcmd, int symlinks, const char *prefix, struct object_id loid, roid; char status; const char *src_path, *dst_path; - size_t src_path_len, dst_path_len; if (starts_with(info.buf, "::")) die(N_("combined diff formats('-c' and '--cc') are " @@ -390,17 +419,14 @@ static int run_dir_diff(const char *extcmd, int symlinks, const char *prefix, if (strbuf_getline_nul(&lpath, fp)) break; src_path = lpath.buf; - src_path_len = lpath.len; i++; if (status != 'C' && status != 'R') { dst_path = src_path; - dst_path_len = src_path_len; } else { if (strbuf_getline_nul(&rpath, fp)) break; dst_path = rpath.buf; - dst_path_len = rpath.len; } if (S_ISGITLINK(lmode) || S_ISGITLINK(rmode)) { @@ -430,12 +456,10 @@ static int run_dir_diff(const char *extcmd, int symlinks, const char *prefix, } if (lmode && status != 'C') { - ce->ce_mode = lmode; - oidcpy(&ce->oid, &loid); - strcpy(ce->name, src_path); - ce->ce_namelen = src_path_len; - if (checkout_entry(ce, &lstate, NULL)) - return error("could not write '%s'", src_path); + if (checkout_path(lmode, &loid, src_path, &lstate)) { + ret = error("could not write '%s'", src_path); + goto finish; + } } if (rmode && !S_ISLNK(rmode)) { @@ -451,13 +475,12 @@ static int run_dir_diff(const char *extcmd, int symlinks, const char *prefix, hashmap_add(&working_tree_dups, entry); if (!use_wt_file(workdir, dst_path, &roid)) { - ce->ce_mode = rmode; - oidcpy(&ce->oid, &roid); - strcpy(ce->name, dst_path); - ce->ce_namelen = dst_path_len; - if (checkout_entry(ce, &rstate, NULL)) - return error("could not write '%s'", - dst_path); + if (checkout_path(rmode, &roid, dst_path, + &rstate)) { + ret = error("could not write '%s'", + dst_path); + goto finish; + } } else if (!is_null_oid(&roid)) { /* * Changes in the working tree need special @@ -472,10 +495,12 @@ static int run_dir_diff(const char *extcmd, int symlinks, const char *prefix, ADD_CACHE_JUST_APPEND); add_path(&rdir, rdir_len, dst_path); - if (ensure_leading_directories(rdir.buf)) - return error("could not create " - "directory for '%s'", - dst_path); + if (ensure_leading_directories(rdir.buf)) { + ret = error("could not create " + "directory for '%s'", + dst_path); + goto finish; + } add_path(&wtdir, wtdir_len, dst_path); if (symlinks) { if (symlink(wtdir.buf, rdir.buf)) { @@ -496,13 +521,15 @@ static int run_dir_diff(const char *extcmd, int symlinks, const char *prefix, } } + fclose(fp); + fp = NULL; if (finish_command(&child)) { ret = error("error occurred running diff --raw"); goto finish; } if (!i) - return 0; + goto finish; /* * Changes to submodules require special treatment.This loop writes a @@ -567,10 +594,8 @@ static int run_dir_diff(const char *extcmd, int symlinks, const char *prefix, * in the common case of --symlinks and the difftool updating * files through the symlink. */ - hashmap_init(&wt_modified, (hashmap_cmp_fn)path_entry_cmp, - wtindex.cache_nr); - hashmap_init(&tmp_modified, (hashmap_cmp_fn)path_entry_cmp, - wtindex.cache_nr); + hashmap_init(&wt_modified, path_entry_cmp, NULL, wtindex.cache_nr); + hashmap_init(&tmp_modified, path_entry_cmp, NULL, wtindex.cache_nr); for (i = 0; i < wtindex.cache_nr; i++) { struct hashmap_entry dummy; @@ -625,7 +650,11 @@ static int run_dir_diff(const char *extcmd, int symlinks, const char *prefix, exit_cleanup(tmpdir, rc); finish: - free(ce); + if (fp) + fclose(fp); + + free(lbase_dir); + free(rbase_dir); strbuf_release(&ldir); strbuf_release(&rdir); strbuf_release(&wtdir); |