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_state {
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_state * dt_state = (struct difftool_state * )cb ;
49
52
if (!strcmp (var , "difftool.trustexitcode" )) {
50
- trust_exit_code = git_config_bool (var , value );
53
+ dt_state -> trust_exit_code = git_config_bool (var , value );
54
+ return 0 ;
55
+ }
56
+ if (!strcmp (var , "core.symlinks" )) {
57
+ dt_state -> has_symlinks = git_config_bool (var , value );
51
58
return 0 ;
52
59
}
53
60
@@ -63,7 +70,8 @@ static int print_tool_help(void)
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,11 +83,11 @@ static int parse_index_info(char *p, int *mode1, int *mode2,
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,7 +114,8 @@ static void add_path(struct strbuf *buf, size_t base_len, const char *path)
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,7 +130,7 @@ static int use_wt_file(const char *workdir, const char *name,
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,13 +221,14 @@ static int path_entry_cmp(const void *cmp_data UNUSED,
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,13 +301,15 @@ static int ensure_leading_directories(char *path)
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_state * dt_state ,
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_state -> 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,8 +319,7 @@ static char *get_symlink(const struct object_id *oid, const char *path)
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,7 +366,9 @@ static void write_standin_files(struct pair_entry *entry,
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_state * dt_state ,
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,15 +388,15 @@ static int run_dir_diff(const char *extcmd, int symlinks, const char *prefix,
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 ;
382
395
struct hashmap wt_modified = HASHMAP_INIT (path_entry_cmp , NULL );
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,8 +451,7 @@ static int run_dir_diff(const char *extcmd, int symlinks, const char *prefix,
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,13 +481,13 @@ static int run_dir_diff(const char *extcmd, int symlinks, const char *prefix,
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_state , & 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_state , & roid , dst_path );
479
491
add_left_or_right (& symlinks2 , dst_path , content , 1 );
480
492
free (content );
481
493
}
@@ -500,7 +512,7 @@ static int run_dir_diff(const char *extcmd, int symlinks, const char *prefix,
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,7 +540,7 @@ static int run_dir_diff(const char *extcmd, int symlinks, const char *prefix,
528
540
goto finish ;
529
541
}
530
542
add_path (& wtdir , wtdir_len , dst_path );
531
- if (symlinks ) {
543
+ if (dt_state -> 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,7 +626,7 @@ static int run_dir_diff(const char *extcmd, int symlinks, const char *prefix,
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_state -> symlinks && S_ISLNK (st .st_mode )) || !S_ISREG (st .st_mode ))
618
630
continue ;
619
631
620
632
if (!indices_loaded ) {
@@ -626,9 +638,9 @@ static int run_dir_diff(const char *extcmd, int symlinks, const char *prefix,
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,11 +714,15 @@ static int run_file_diff(int prompt, const char *prefix,
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_state dt_state = {
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,14 +733,14 @@ int cmd_difftool(int argc,
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_state . 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_state . 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,8 +750,9 @@ int cmd_difftool(int argc,
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_state );
755
+ dt_state .symlinks = dt_state .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,8 +766,8 @@ int cmd_difftool(int argc,
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,7 +800,7 @@ int cmd_difftool(int argc,
783
800
}
784
801
785
802
setenv ("GIT_DIFFTOOL_TRUST_EXIT_CODE" ,
786
- trust_exit_code ? "true" : "false" , 1 );
803
+ dt_state . trust_exit_code ? "true" : "false" , 1 );
787
804
788
805
/*
789
806
* In directory diff mode, 'git-difftool--helper' is called once
@@ -799,6 +816,6 @@ int cmd_difftool(int argc,
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_state , extcmd , prefix , & child );
803
820
return run_file_diff (prompt , prefix , & child );
804
821
}
0 commit comments