Git fork

Merge branch 'da/difftool-sans-the-repository'

"git difftool" code clean-up.

* da/difftool-sans-the-repository:
difftool: eliminate use of USE_THE_REPOSITORY_VARIABLE
difftool: eliminate use of the_repository
difftool: eliminate use of global variables

+56 -39
+56 -39
builtin/difftool.c
··· 12 12 * Copyright (C) 2016 Johannes Schindelin 13 13 */ 14 14 15 - #define USE_THE_REPOSITORY_VARIABLE 16 - 17 15 #include "builtin.h" 18 16 19 17 #include "abspath.h" ··· 36 34 #include "entry.h" 37 35 #include "setup.h" 38 36 39 - static int trust_exit_code; 40 - 41 37 static const char *const builtin_difftool_usage[] = { 42 38 N_("git difftool [<options>] [<commit> [<commit>]] [--] [<path>...]"), 43 39 NULL 44 40 }; 45 41 42 + struct difftool_options { 43 + int has_symlinks; 44 + int symlinks; 45 + int trust_exit_code; 46 + }; 47 + 46 48 static int difftool_config(const char *var, const char *value, 47 49 const struct config_context *ctx, void *cb) 48 50 { 51 + struct difftool_options *dt_options = (struct difftool_options *)cb; 49 52 if (!strcmp(var, "difftool.trustexitcode")) { 50 - trust_exit_code = git_config_bool(var, value); 53 + dt_options->trust_exit_code = git_config_bool(var, value); 54 + return 0; 55 + } 56 + if (!strcmp(var, "core.symlinks")) { 57 + dt_options->has_symlinks = git_config_bool(var, value); 51 58 return 0; 52 59 } 53 60 ··· 63 70 return run_command(&cmd); 64 71 } 65 72 66 - static int parse_index_info(char *p, int *mode1, int *mode2, 73 + static int parse_index_info(struct repository *repo, 74 + char *p, int *mode1, int *mode2, 67 75 struct object_id *oid1, struct object_id *oid2, 68 76 char *status) 69 77 { ··· 75 83 *mode2 = (int)strtol(p + 1, &p, 8); 76 84 if (*p != ' ') 77 85 return error("expected ' ', got '%c'", *p); 78 - if (parse_oid_hex(++p, oid1, (const char **)&p)) 86 + if (parse_oid_hex_algop(++p, oid1, (const char **)&p, repo->hash_algo)) 79 87 return error("expected object ID, got '%s'", p); 80 88 if (*p != ' ') 81 89 return error("expected ' ', got '%c'", *p); 82 - if (parse_oid_hex(++p, oid2, (const char **)&p)) 90 + if (parse_oid_hex_algop(++p, oid2, (const char **)&p, repo->hash_algo)) 83 91 return error("expected object ID, got '%s'", p); 84 92 if (*p != ' ') 85 93 return error("expected ' ', got '%c'", *p); ··· 106 114 /* 107 115 * Determine whether we can simply reuse the file in the worktree. 108 116 */ 109 - static int use_wt_file(const char *workdir, const char *name, 117 + static int use_wt_file(struct repository *repo, 118 + const char *workdir, const char *name, 110 119 struct object_id *oid) 111 120 { 112 121 struct strbuf buf = STRBUF_INIT; ··· 121 130 int fd = open(buf.buf, O_RDONLY); 122 131 123 132 if (fd >= 0 && 124 - !index_fd(the_repository->index, &wt_oid, fd, &st, OBJ_BLOB, name, 0)) { 133 + !index_fd(repo->index, &wt_oid, fd, &st, OBJ_BLOB, name, 0)) { 125 134 if (is_null_oid(oid)) { 126 135 oidcpy(oid, &wt_oid); 127 136 use = 1; ··· 212 221 return strcmp(a->path, key ? key : b->path); 213 222 } 214 223 215 - static void changed_files(struct hashmap *result, const char *index_path, 224 + static void changed_files(struct repository *repo, 225 + struct hashmap *result, const char *index_path, 216 226 const char *workdir) 217 227 { 218 228 struct child_process update_index = CHILD_PROCESS_INIT; 219 229 struct child_process diff_files = CHILD_PROCESS_INIT; 220 230 struct strbuf buf = STRBUF_INIT; 221 - const char *git_dir = absolute_path(repo_get_git_dir(the_repository)); 231 + const char *git_dir = absolute_path(repo_get_git_dir(repo)); 222 232 FILE *fp; 223 233 224 234 strvec_pushl(&update_index.args, ··· 291 301 * to compare the readlink(2) result as text, even on a filesystem that is 292 302 * capable of doing a symbolic link. 293 303 */ 294 - static char *get_symlink(const struct object_id *oid, const char *path) 304 + static char *get_symlink(struct repository *repo, 305 + struct difftool_options *dt_options, 306 + const struct object_id *oid, const char *path) 295 307 { 296 308 char *data; 297 309 if (is_null_oid(oid)) { 298 310 /* The symlink is unknown to Git so read from the filesystem */ 299 311 struct strbuf link = STRBUF_INIT; 300 - if (has_symlinks) { 312 + if (dt_options->has_symlinks) { 301 313 if (strbuf_readlink(&link, path, strlen(path))) 302 314 die(_("could not read symlink %s"), path); 303 315 } else if (strbuf_read_file(&link, path, 128)) ··· 307 319 } else { 308 320 enum object_type type; 309 321 unsigned long size; 310 - data = repo_read_object_file(the_repository, oid, &type, 311 - &size); 322 + data = repo_read_object_file(repo, oid, &type, &size); 312 323 if (!data) 313 324 die(_("could not read object %s for symlink %s"), 314 325 oid_to_hex(oid), path); ··· 355 366 write_file_in_directory(rdir, rdir_len, entry->path, entry->right); 356 367 } 357 368 358 - static int run_dir_diff(const char *extcmd, int symlinks, const char *prefix, 369 + static int run_dir_diff(struct repository *repo, 370 + struct difftool_options *dt_options, 371 + const char *extcmd, const char *prefix, 359 372 struct child_process *child) 360 373 { 361 374 struct strbuf info = STRBUF_INIT, lpath = STRBUF_INIT; ··· 375 388 struct hashmap symlinks2 = HASHMAP_INIT(pair_cmp, NULL); 376 389 struct hashmap_iter iter; 377 390 struct pair_entry *entry; 378 - struct index_state wtindex = INDEX_STATE_INIT(the_repository); 391 + struct index_state wtindex = INDEX_STATE_INIT(repo); 379 392 struct checkout lstate, rstate; 380 393 int err = 0; 381 394 struct child_process cmd = CHILD_PROCESS_INIT; ··· 383 396 struct hashmap tmp_modified = HASHMAP_INIT(path_entry_cmp, NULL); 384 397 int indices_loaded = 0; 385 398 386 - workdir = repo_get_work_tree(the_repository); 399 + workdir = repo_get_work_tree(repo); 387 400 388 401 /* Setup temp directories */ 389 402 tmp = getenv("TMPDIR"); ··· 438 451 "not supported in\n" 439 452 "directory diff mode ('-d' and '--dir-diff').")); 440 453 441 - if (parse_index_info(info.buf, &lmode, &rmode, &loid, &roid, 442 - &status)) 454 + if (parse_index_info(repo, info.buf, &lmode, &rmode, &loid, &roid, &status)) 443 455 break; 444 456 if (strbuf_getline_nul(&lpath, fp)) 445 457 break; ··· 469 481 } 470 482 471 483 if (S_ISLNK(lmode)) { 472 - char *content = get_symlink(&loid, src_path); 484 + char *content = get_symlink(repo, dt_options, &loid, src_path); 473 485 add_left_or_right(&symlinks2, src_path, content, 0); 474 486 free(content); 475 487 } 476 488 477 489 if (S_ISLNK(rmode)) { 478 - char *content = get_symlink(&roid, dst_path); 490 + char *content = get_symlink(repo, dt_options, &roid, dst_path); 479 491 add_left_or_right(&symlinks2, dst_path, content, 1); 480 492 free(content); 481 493 } ··· 500 512 } 501 513 hashmap_add(&working_tree_dups, &entry->entry); 502 514 503 - if (!use_wt_file(workdir, dst_path, &roid)) { 515 + if (!use_wt_file(repo, workdir, dst_path, &roid)) { 504 516 if (checkout_path(rmode, &roid, dst_path, 505 517 &rstate)) { 506 518 ret = error("could not write '%s'", ··· 528 540 goto finish; 529 541 } 530 542 add_path(&wtdir, wtdir_len, dst_path); 531 - if (symlinks) { 543 + if (dt_options->symlinks) { 532 544 if (symlink(wtdir.buf, rdir.buf)) { 533 545 ret = error_errno("could not symlink '%s' to '%s'", wtdir.buf, rdir.buf); 534 546 goto finish; ··· 614 626 if (lstat(rdir.buf, &st)) 615 627 continue; 616 628 617 - if ((symlinks && S_ISLNK(st.st_mode)) || !S_ISREG(st.st_mode)) 629 + if ((dt_options->symlinks && S_ISLNK(st.st_mode)) || !S_ISREG(st.st_mode)) 618 630 continue; 619 631 620 632 if (!indices_loaded) { ··· 626 638 ret = error("could not write %s", buf.buf); 627 639 goto finish; 628 640 } 629 - changed_files(&wt_modified, buf.buf, workdir); 641 + changed_files(repo, &wt_modified, buf.buf, workdir); 630 642 strbuf_setlen(&rdir, rdir_len); 631 - changed_files(&tmp_modified, buf.buf, rdir.buf); 643 + changed_files(repo, &tmp_modified, buf.buf, rdir.buf); 632 644 add_path(&rdir, rdir_len, name); 633 645 indices_loaded = 1; 634 646 } ··· 702 714 int cmd_difftool(int argc, 703 715 const char **argv, 704 716 const char *prefix, 705 - struct repository *repo UNUSED) 717 + struct repository *repo) 706 718 { 707 - int use_gui_tool = -1, dir_diff = 0, prompt = -1, symlinks = 0, 708 - tool_help = 0, no_index = 0; 719 + int use_gui_tool = -1, dir_diff = 0, prompt = -1, tool_help = 0, no_index = 0; 709 720 static char *difftool_cmd = NULL, *extcmd = NULL; 721 + struct difftool_options dt_options = { 722 + .has_symlinks = 1, 723 + .symlinks = 1, 724 + .trust_exit_code = 0 725 + }; 710 726 struct option builtin_difftool_options[] = { 711 727 OPT_BOOL('g', "gui", &use_gui_tool, 712 728 N_("use `diff.guitool` instead of `diff.tool`")), ··· 717 733 0, PARSE_OPT_NONEG), 718 734 OPT_SET_INT_F(0, "prompt", &prompt, NULL, 719 735 1, PARSE_OPT_NONEG | PARSE_OPT_HIDDEN), 720 - OPT_BOOL(0, "symlinks", &symlinks, 736 + OPT_BOOL(0, "symlinks", &dt_options.symlinks, 721 737 N_("use symlinks in dir-diff mode")), 722 738 OPT_STRING('t', "tool", &difftool_cmd, N_("tool"), 723 739 N_("use the specified diff tool")), 724 740 OPT_BOOL(0, "tool-help", &tool_help, 725 741 N_("print a list of diff tools that may be used with " 726 742 "`--tool`")), 727 - OPT_BOOL(0, "trust-exit-code", &trust_exit_code, 743 + OPT_BOOL(0, "trust-exit-code", &dt_options.trust_exit_code, 728 744 N_("make 'git-difftool' exit when an invoked diff " 729 745 "tool returns a non-zero exit code")), 730 746 OPT_STRING('x', "extcmd", &extcmd, N_("command"), ··· 734 750 }; 735 751 struct child_process child = CHILD_PROCESS_INIT; 736 752 737 - git_config(difftool_config, NULL); 738 - symlinks = has_symlinks; 753 + if (repo) 754 + repo_config(repo, difftool_config, &dt_options); 755 + dt_options.symlinks = dt_options.has_symlinks; 739 756 740 757 argc = parse_options(argc, argv, prefix, builtin_difftool_options, 741 758 builtin_difftool_usage, PARSE_OPT_KEEP_UNKNOWN_OPT | ··· 749 766 750 767 if (!no_index){ 751 768 setup_work_tree(); 752 - setenv(GIT_DIR_ENVIRONMENT, absolute_path(repo_get_git_dir(the_repository)), 1); 753 - setenv(GIT_WORK_TREE_ENVIRONMENT, absolute_path(repo_get_work_tree(the_repository)), 1); 769 + setenv(GIT_DIR_ENVIRONMENT, absolute_path(repo_get_git_dir(repo)), 1); 770 + setenv(GIT_WORK_TREE_ENVIRONMENT, absolute_path(repo_get_work_tree(repo)), 1); 754 771 } else if (dir_diff) 755 772 die(_("options '%s' and '%s' cannot be used together"), "--dir-diff", "--no-index"); 756 773 ··· 783 800 } 784 801 785 802 setenv("GIT_DIFFTOOL_TRUST_EXIT_CODE", 786 - trust_exit_code ? "true" : "false", 1); 803 + dt_options.trust_exit_code ? "true" : "false", 1); 787 804 788 805 /* 789 806 * In directory diff mode, 'git-difftool--helper' is called once ··· 799 816 strvec_pushv(&child.args, argv); 800 817 801 818 if (dir_diff) 802 - return run_dir_diff(extcmd, symlinks, prefix, &child); 819 + return run_dir_diff(repo, &dt_options, extcmd, prefix, &child); 803 820 return run_file_diff(prompt, prefix, &child); 804 821 }