2929#include "quote.h"
3030#include "setup.h"
3131#include "trace.h"
32+ #include "strvec.h"
33+ #include "config.h"
3234
3335struct trace_key trace_default_key = { "GIT_TRACE" , 0 , 0 , 0 };
3436struct trace_key trace_perf_key = TRACE_KEY_INIT (PERFORMANCE );
@@ -53,15 +55,28 @@ static int get_trace_fd(struct trace_key *key, const char *override_envvar)
5355 else if (strlen (trace ) == 1 && isdigit (* trace ))
5456 key -> fd = atoi (trace );
5557 else if (is_absolute_path (trace )) {
56- int fd = open (trace , O_WRONLY | O_APPEND | O_CREAT , 0666 );
58+ struct strbuf name = STRBUF_INIT ;
59+ int fd ;
60+
61+ while (strbuf_expand_step (& name , & trace )) {
62+ if (skip_prefix (trace , "%" , & trace ))
63+ strbuf_addch (& name , '%' );
64+ else if (skip_prefix (trace , "p" , & trace ))
65+ strbuf_addf (& name , "%lu" , (unsigned long )getpid ());
66+ else
67+ strbuf_addch (& name , '%' );
68+ }
69+
70+ fd = open (name .buf , O_WRONLY | O_APPEND | O_CREAT , 0666 );
5771 if (fd == -1 ) {
5872 warning ("could not open '%s' for tracing: %s" ,
59- trace , strerror (errno ));
73+ name . buf , strerror (errno ));
6074 trace_disable (key );
6175 } else {
6276 key -> fd = fd ;
6377 key -> need_close = 1 ;
6478 }
79+ strbuf_release (& name );
6580 } else {
6681 warning ("unknown trace value for '%s': %s\n"
6782 " If you want to trace into a file, then please set %s\n"
@@ -116,8 +131,9 @@ static int prepare_trace_line(const char *file, int line,
116131 localtime_r (& secs , & tm );
117132 strbuf_addf (buf , "%02d:%02d:%02d.%06ld %s:%d" , tm .tm_hour , tm .tm_min ,
118133 tm .tm_sec , (long ) tv .tv_usec , file , line );
119- /* align trace output (column 40 catches most files names in git) */
120- while (buf -> len < 40 )
134+ strbuf_addf (buf , "[pid=%lu] " , (unsigned long )getpid ());
135+ /* align trace output (column 50 catches most files names in git) */
136+ while (buf -> len < 50 )
121137 strbuf_addch (buf , ' ' );
122138
123139 return 1 ;
@@ -428,3 +444,47 @@ void trace_command_performance(const char **argv)
428444 sq_quote_argv_pretty (& command_line , argv );
429445 trace_performance_enter ();
430446}
447+
448+ struct trace_config_data {
449+ const char * want_cmd ;
450+ struct strvec * out ;
451+ };
452+
453+ static int trace_config_cb (const char * var , const char * value ,
454+ const struct config_context * ctx UNUSED , void * vdata )
455+ {
456+ struct trace_config_data * data = vdata ;
457+ const char * have_cmd , * key ;
458+ size_t have_len ;
459+
460+ if (!parse_config_key (var , "trace" , & have_cmd , & have_len , & key ) &&
461+ have_cmd &&
462+ !strncmp (data -> want_cmd , have_cmd , have_len ) &&
463+ data -> want_cmd [have_len ] == '\0' ) {
464+ struct strbuf buf = STRBUF_INIT ;
465+
466+ strbuf_addstr (& buf , "GIT_TRACE_" );
467+ while (* key )
468+ strbuf_addch (& buf , toupper (* key ++ ));
469+
470+ /*
471+ * Environment always takes precedence over config, so do not
472+ * override existing variables. We cannot rely on setenv()'s
473+ * overwrite flag here, because we may pass the list off to
474+ * a spawn() implementation, which always overwrites.
475+ */
476+ if (!getenv (buf .buf ))
477+ strvec_pushf (data -> out , "%s=%s" , buf .buf , value );
478+
479+ strbuf_release (& buf );
480+ }
481+ return 0 ;
482+ }
483+
484+ void trace_config_for (struct repository * r , const char * cmd , struct strvec * out )
485+ {
486+ struct trace_config_data data ;
487+ data .want_cmd = cmd ;
488+ data .out = out ;
489+ repo_config (r , trace_config_cb , & data );
490+ }
0 commit comments