Skip to content
Closed
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,350 changes: 1,350 additions & 0 deletions Documentation/technical/api-trace2.txt

Large diffs are not rendered by default.

14 changes: 13 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -1005,6 +1005,16 @@ LIB_OBJS += tempfile.o
LIB_OBJS += thread-utils.o
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On the Git mailing list, =?utf-8?B?w4Z2YXIgQXJuZmrDtnLDsA==?= Bjarmason wrote (reply to this):


On Wed, Feb 06 2019, Jeff Hostetler via GitGitGadget wrote:

> +	sa.sun_family = AF_UNIX;
> +	strlcpy(sa.sun_path, path, sizeof(sa.sun_path));
> +	if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1 ||
> +	    connect(fd, (struct sockaddr *)&sa, sizeof(sa)) == -1) {
> +		if (tr2_dst_want_warning())
> +			warning("trace2: could not connect to socket '%s' for '%s' tracing: %s",
> +				path, dst->env_var_name, strerror(errno));
> +
> +		tr2_dst_trace_disable(dst);
> +		return 0;
> +	}

Just curious, what do you use af_unix:* for? Is this provided by some
Windows emulation ?

On Linux with systemd, this does not work for logging to systemd's
/dev/log. You're opening the socket with SOCK_STREAM, but it needs
SOCK_DGRAM. I.e.:

    # fail
    echo '{"yay": "testing"}' | nc -U /dev/log
    # works
    echo '{"yay": "testing"}' | nc -uU /dev/log

So that gives something that'll "work" for "jounalctl -f", but on my
system ends up being munged to the invalid JSON:

    '{"yay"[PID]: "testing"}'.

I found, and this may be specific to the systemd/rsyslog setup on RedHat
I'm working with, that what /dev/log is expecting is a payload in the
syslog format: https://tools.ietf.org/html/rfc5424

So related to my question in
https://public-inbox.org/git/87a7iyk0r8.fsf@evledraar.gmail.com/ I
wonder what we should do about this. It seems the bare minimal thing
that's needed it some way to open a socket with SOCK_DGRAM, maybe we
should just do that unconditionally if the connect() fails with
EPROTOTYPE?

But it seems that for that to be useful for systemd we'd need to support
the syslog.h interface (so different from af_unix:*), or learn how to
write a standard syslog packet to an af_unix:* SOCK_DGRAM socket.

I guess we can start with just supporting that by hardcoding the ident &
LOG_* values to something sensible, e.g.:

  openlog("git", LOG_PID | (tr2_dst_want_warning() ? LOG_CONS : 0), LOG_USER);
  syslog(LOG_USER|LOG_DEBUG, message_or_json);
  closelog();

I can write the patches for this. As in the earlier message I'm just
looking for some context, whether this is stuff you have WIP already,
and whether you have any other/related ideas. Thanks.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On the Git mailing list, Jeff Hostetler wrote (reply to this):



On 2/15/2019 11:00 AM, Ævar Arnfjörð Bjarmason wrote:
> 
> On Wed, Feb 06 2019, Jeff Hostetler via GitGitGadget wrote:
> 
>> +	sa.sun_family = AF_UNIX;
>> +	strlcpy(sa.sun_path, path, sizeof(sa.sun_path));
>> +	if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1 ||
>> +	    connect(fd, (struct sockaddr *)&sa, sizeof(sa)) == -1) {
>> +		if (tr2_dst_want_warning())
>> +			warning("trace2: could not connect to socket '%s' for '%s' tracing: %s",
>> +				path, dst->env_var_name, strerror(errno));
>> +
>> +		tr2_dst_trace_disable(dst);
>> +		return 0;
>> +	}
> 
> Just curious, what do you use af_unix:* for? Is this provided by some
> Windows emulation ?

On the Mac, I want to send data to a server that only handles
stream data.  I thought about making the prefix something like
     "af_unix:stream:<path>"
and then we could have the correpsonding dgram version too, but
I didn't add that.

I think I'll add this in the next re-roll.



> On Linux with systemd, this does not work for logging to systemd's
> /dev/log. You're opening the socket with SOCK_STREAM, but it needs
> SOCK_DGRAM. I.e.:
> 
>      # fail
>      echo '{"yay": "testing"}' | nc -U /dev/log
>      # works
>      echo '{"yay": "testing"}' | nc -uU /dev/log
> 
> So that gives something that'll "work" for "jounalctl -f", but on my
> system ends up being munged to the invalid JSON:
> 
>      '{"yay"[PID]: "testing"}'.
> 
> I found, and this may be specific to the systemd/rsyslog setup on RedHat
> I'm working with, that what /dev/log is expecting is a payload in the
> syslog format: https://tools.ietf.org/html/rfc5424
> 
> So related to my question in
> https://public-inbox.org/git/87a7iyk0r8.fsf@evledraar.gmail.com/ I
> wonder what we should do about this. It seems the bare minimal thing
> that's needed it some way to open a socket with SOCK_DGRAM, maybe we
> should just do that unconditionally if the connect() fails with
> EPROTOTYPE?
> 
> But it seems that for that to be useful for systemd we'd need to support
> the syslog.h interface (so different from af_unix:*), or learn how to
> write a standard syslog packet to an af_unix:* SOCK_DGRAM socket.
> 
> I guess we can start with just supporting that by hardcoding the ident &
> LOG_* values to something sensible, e.g.:
> 
>    openlog("git", LOG_PID | (tr2_dst_want_warning() ? LOG_CONS : 0), LOG_USER);
>    syslog(LOG_USER|LOG_DEBUG, message_or_json);
>    closelog();
> 
> I can write the patches for this. As in the earlier message I'm just
> looking for some context, whether this is stuff you have WIP already,
> and whether you have any other/related ideas. Thanks.
> 

When I created the "af_unix:" prefix for Unix domain sockets, I thought
we could later do other types of sockets if we wanted to.  The common
theme being they just need an "fd".

For syslog(), rather than changing the af_unix socket code, you could
create a new Trace2 target.  For example, copy one of the existing
targets:
    trace2/tr2_tgt_normal.c that defines GIT_TR2
    trace2/tr2_tgt_event.c that defines GIT_TR2_EVENT
    trace2/tr2_tgt_perf.c that defines GIT_TR2_PERF
and create:
    trace2/tr2_tgt_syslog.c that defines GIT_TR2_SYSLOG.

Then in tr2_tgt_syslog.c you have complete control of the formatting
of the data you send to syslog().  You can omit fields as necessary.
Or you can printf format it rather than JSON encode it.

Then in trace2/tr2_dst.c add a parser for "syslog:<whatever>".
All it has to do is set a bit so that tr2_dst_trace_want()
returns true if you were able to openlog().

Hope that helps,
Jeff


Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On the Git mailing list, SZEDER Gábor wrote (reply to this):

On Fri, Feb 22, 2019 at 02:25:01PM -0800, Jeff Hostetler via GitGitGadget wrote:
> From: Jeff Hostetler <jeffhost@microsoft.com>
> 
> Create a new unified tracing facility for git.  The eventual intent is to
> replace the current trace_printf* and trace_performance* routines with a
> unified set of git_trace2* routines.
> 
> In addition to the usual printf-style API, trace2 provides higer-level
> event verbs with fixed-fields allowing structured data to be written.
> This makes post-processing and analysis easier for external tools.
> 
> Trace2 defines 3 output targets.  These are set using the environment
> variables "GIT_TR2", "GIT_TR2_PERF", and "GIT_TR2_EVENT".  These may be
> set to "1" or to an absolute pathname (just like the current GIT_TRACE).
> 
> * GIT_TR2 is intended to be a replacement for GIT_TRACE and logs command
>   summary data.
> 
> * GIT_TR2_PERF is intended as a replacement for GIT_TRACE_PERFORMANCE.
>   It extends the output with columns for the command process, thread,
>   repo, absolute and relative elapsed times.  It reports events for
>   child process start/stop, thread start/stop, and per-thread function
>   nesting.
> 
> * GIT_TR2_EVENT is a new structured format. It writes event data as a
>   series of JSON records.

Please document these new environment variables in
'Documentation/git.txt', where the other environment variables,
including GIT_TRACE_*, are already documented.

While doing so, please note that the description about the possible
values of these variables and of GIT_TRACE above is incomplete,
because it's not just "1" or an absolute pathname.  Quoting the
description of GIT_TRACE:

  If this variable is set to "1", "2" or "true" (comparison is case
  insensitive), trace messages will be printed to stderr.
  
  If the variable is set to an integer value greater than 2 and lower
  than 10 (strictly) then Git will interpret this value as an open
  file descriptor and will try to write the trace messages into this
  file descriptor.

The way I see it in tr2_dst_get_trace_fd() below, this applies to
GIT_TRACE2* as well, and it even offers the possibility to specify a
Unix Domain Socket, too.


And sorry for barging in with a big bucket of paint this late, but,
really...  why GIT_TR2 instead of GIT_TRACE2?


> +int tr2_dst_get_trace_fd(struct tr2_dst *dst)
> +{
> +	const char *tgt_value;
> +
> +	/* don't open twice */
> +	if (dst->initialized)
> +		return dst->fd;
> +
> +	dst->initialized = 1;
> +
> +	tgt_value = getenv(dst->env_var_name);
> +
> +	if (!tgt_value || !strcmp(tgt_value, "") || !strcmp(tgt_value, "0") ||
> +	    !strcasecmp(tgt_value, "false")) {
> +		dst->fd = 0;
> +		return dst->fd;
> +	}
> +
> +	if (!strcmp(tgt_value, "1") || !strcasecmp(tgt_value, "true")) {
> +		dst->fd = STDERR_FILENO;
> +		return dst->fd;
> +	}
> +
> +	if (strlen(tgt_value) == 1 && isdigit(*tgt_value)) {
> +		dst->fd = atoi(tgt_value);
> +		return dst->fd;
> +	}
> +
> +	if (is_absolute_path(tgt_value))
> +		return tr2_dst_try_path(dst, tgt_value);
> +
> +#ifndef NO_UNIX_SOCKETS
> +	if (starts_with(tgt_value, PREFIX_AF_UNIX))
> +		return tr2_dst_try_unix_domain_socket(dst, tgt_value);
> +#endif
> +
> +	/* Always warn about malformed values. */
> +	tr2_dst_malformed_warning(dst, tgt_value);
> +	tr2_dst_trace_disable(dst);
> +	return 0;
> +}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On the Git mailing list, Derrick Stolee wrote (reply to this):

On 5/10/2019 1:28 PM, SZEDER Gábor wrote:
> On Fri, Feb 22, 2019 at 02:25:01PM -0800, Jeff Hostetler via GitGitGadget wrote:
>> From: Jeff Hostetler <jeffhost@microsoft.com>
>>
>> * GIT_TR2_EVENT is a new structured format. It writes event data as a
>>   series of JSON records.
> 
> Please document these new environment variables in
> 'Documentation/git.txt', where the other environment variables,
> including GIT_TRACE_*, are already documented.

Thanks for the report!
 
> While doing so, please note that the description about the possible
> values of these variables and of GIT_TRACE above is incomplete,
> because it's not just "1" or an absolute pathname.  Quoting the
> description of GIT_TRACE:
> 
>   If this variable is set to "1", "2" or "true" (comparison is case
>   insensitive), trace messages will be printed to stderr.
>   
>   If the variable is set to an integer value greater than 2 and lower
>   than 10 (strictly) then Git will interpret this value as an open
>   file descriptor and will try to write the trace messages into this
>   file descriptor.
> 
> The way I see it in tr2_dst_get_trace_fd() below, this applies to
> GIT_TRACE2* as well, and it even offers the possibility to specify a
> Unix Domain Socket, too.


Please see [1] for a possible direction here.

[1] https://public-inbox.org/git/pull.189.git.gitgitgadget@gmail.com/


> And sorry for barging in with a big bucket of paint this late, but,
> really...  why GIT_TR2 instead of GIT_TRACE2?

I did not do anything in response to this. I'll leave that discussion
to others.

Thanks,
-Stolee

LIB_OBJS += tmp-objdir.o
LIB_OBJS += trace.o
LIB_OBJS += trace2.o
LIB_OBJS += trace2/tr2_cfg.o
LIB_OBJS += trace2/tr2_cmd_name.o
LIB_OBJS += trace2/tr2_dst.o
LIB_OBJS += trace2/tr2_sid.o
LIB_OBJS += trace2/tr2_tbuf.o
LIB_OBJS += trace2/tr2_tgt_event.o
LIB_OBJS += trace2/tr2_tgt_normal.o
LIB_OBJS += trace2/tr2_tgt_perf.o
LIB_OBJS += trace2/tr2_tls.o
LIB_OBJS += trailer.o
LIB_OBJS += transport.o
LIB_OBJS += transport-helper.o
Expand Down Expand Up @@ -1581,7 +1591,9 @@ ifdef NO_INET_PTON
LIB_OBJS += compat/inet_pton.o
BASIC_CFLAGS += -DNO_INET_PTON
endif
ifndef NO_UNIX_SOCKETS
ifdef NO_UNIX_SOCKETS
BASIC_CFLAGS += -DNO_UNIX_SOCKETS
else
LIB_OBJS += unix-socket.o
PROGRAM_OBJS += credential-cache.o
PROGRAM_OBJS += credential-cache--daemon.o
Expand Down
9 changes: 4 additions & 5 deletions builtin/submodule--helper.c
Original file line number Diff line number Diff line change
Expand Up @@ -1815,11 +1815,10 @@ static int update_submodules(struct submodule_update_clone *suc)
{
int i;

run_processes_parallel(suc->max_jobs,
update_clone_get_next_task,
update_clone_start_failure,
update_clone_task_finished,
suc);
run_processes_parallel_tr2(suc->max_jobs, update_clone_get_next_task,
update_clone_start_failure,
update_clone_task_finished, suc, "submodule",
"parallel/update");

/*
* We saved the output and put it out all at once now.
Expand Down
1 change: 1 addition & 0 deletions cache.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include "gettext.h"
#include "convert.h"
#include "trace.h"
#include "trace2.h"
#include "string-list.h"
#include "pack-revindex.h"
#include "hash.h"
Expand Down
12 changes: 10 additions & 2 deletions common-main.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,18 @@ static void restore_sigpipe_to_default(void)

int main(int argc, const char **argv)
{
int result;

/*
* Always open file descriptors 0/1/2 to avoid clobbering files
* in die(). It also avoids messing up when the pipes are dup'ed
* onto stdin/stdout/stderr in the child processes we spawn.
*/
sanitize_stdfds();
restore_sigpipe_to_default();

trace2_initialize();
trace2_cmd_start(argv);

git_resolve_executable_dir(argv[0]);

Expand All @@ -40,7 +46,9 @@ int main(int argc, const char **argv)

attr_start();

restore_sigpipe_to_default();
result = cmd_main(argc, argv);

trace2_cmd_exit(result);

return cmd_main(argc, argv);
return result;
}
11 changes: 10 additions & 1 deletion compat/mingw.c
Original file line number Diff line number Diff line change
Expand Up @@ -1476,19 +1476,23 @@ static int try_shell_exec(const char *cmd, char *const *argv)
return 0;
prog = path_lookup(interpr, 1);
if (prog) {
int exec_id;
int argc = 0;
const char **argv2;
while (argv[argc]) argc++;
ALLOC_ARRAY(argv2, argc + 1);
argv2[0] = (char *)cmd; /* full path to the script file */
memcpy(&argv2[1], &argv[1], sizeof(*argv) * argc);
exec_id = trace2_exec(prog, argv2);
pid = mingw_spawnv(prog, argv2, 1);
if (pid >= 0) {
int status;
if (waitpid(pid, &status, 0) < 0)
status = 255;
trace2_exec_result(exec_id, status);
exit(status);
}
trace2_exec_result(exec_id, -1);
pid = 1; /* indicate that we tried but failed */
free(prog);
free(argv2);
Expand All @@ -1501,12 +1505,17 @@ int mingw_execv(const char *cmd, char *const *argv)
/* check if git_command is a shell script */
if (!try_shell_exec(cmd, argv)) {
int pid, status;
int exec_id;

exec_id = trace2_exec(cmd, (const char **)argv);
pid = mingw_spawnv(cmd, (const char **)argv, 0);
if (pid < 0)
if (pid < 0) {
trace2_exec_result(exec_id, -1);
return -1;
}
if (waitpid(pid, &status, 0) < 0)
status = 255;
trace2_exec_result(exec_id, status);
exit(status);
}
return -1;
Expand Down
3 changes: 1 addition & 2 deletions compat/mingw.h
Original file line number Diff line number Diff line change
Expand Up @@ -147,8 +147,7 @@ static inline int fcntl(int fd, int cmd, ...)
errno = EINVAL;
return -1;
}
/* bash cannot reliably detect negative return codes as failure */
#define exit(code) exit((code) & 0xff)

#define sigemptyset(x) (void)0
static inline int sigaddset(sigset_t *set, int signum)
{ return 0; }
Expand Down
2 changes: 2 additions & 0 deletions config.c
Original file line number Diff line number Diff line change
Expand Up @@ -2656,6 +2656,8 @@ int git_config_set_gently(const char *key, const char *value)
void git_config_set(const char *key, const char *value)
{
git_config_set_multivar(key, value, NULL, 0);

trace2_cmd_set_config(key, value);
}

/*
Expand Down
2 changes: 2 additions & 0 deletions exec-cmd.c
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,8 @@ static int git_get_exec_path(struct strbuf *buf, const char *argv0)
return -1;
}

trace2_cmd_path(buf->buf);

return 0;
}

Expand Down
7 changes: 7 additions & 0 deletions git-compat-util.h
Original file line number Diff line number Diff line change
Expand Up @@ -1251,6 +1251,13 @@ static inline int is_missing_file_error(int errno_)

extern int cmd_main(int, const char **);

/*
* Intercept all calls to exit() and route them to trace2 to
* optionally emit a message before calling the real exit().
*/
int trace2_cmd_exit_fl(const char *file, int line, int code);
#define exit(code) exit(trace2_cmd_exit_fl(__FILE__, __LINE__, (code)))

/*
* You can mark a stack variable with UNLEAK(var) to avoid it being
* reported as a leak by tools like LSAN or valgrind. The argument
Expand Down
65 changes: 65 additions & 0 deletions git.c
Original file line number Diff line number Diff line change
Expand Up @@ -147,16 +147,20 @@ static int handle_options(const char ***argv, int *argc, int *envchanged)
git_set_exec_path(cmd + 1);
else {
puts(git_exec_path());
trace2_cmd_name("_query_");
exit(0);
}
} else if (!strcmp(cmd, "--html-path")) {
puts(system_path(GIT_HTML_PATH));
trace2_cmd_name("_query_");
exit(0);
} else if (!strcmp(cmd, "--man-path")) {
puts(system_path(GIT_MAN_PATH));
trace2_cmd_name("_query_");
exit(0);
} else if (!strcmp(cmd, "--info-path")) {
puts(system_path(GIT_INFO_PATH));
trace2_cmd_name("_query_");
exit(0);
} else if (!strcmp(cmd, "-p") || !strcmp(cmd, "--paginate")) {
use_pager = 1;
Expand Down Expand Up @@ -285,6 +289,7 @@ static int handle_options(const char ***argv, int *argc, int *envchanged)
(*argv)++;
(*argc)--;
} else if (skip_prefix(cmd, "--list-cmds=", &cmd)) {
trace2_cmd_name("_query_");
if (!strcmp(cmd, "parseopt")) {
struct string_list list = STRING_LIST_INIT_DUP;
int i;
Expand Down Expand Up @@ -332,9 +337,14 @@ static int handle_alias(int *argcp, const char ***argv)
commit_pager_choice();

child.use_shell = 1;
child.trace2_child_class = "shell_alias";
argv_array_push(&child.args, alias_string + 1);
argv_array_pushv(&child.args, (*argv) + 1);

trace2_cmd_alias(alias_command, child.args.argv);
trace2_cmd_list_config();
trace2_cmd_name("_run_shell_alias_");

ret = run_command(&child);
if (ret >= 0) /* normal exit */
exit(ret);
Expand Down Expand Up @@ -369,6 +379,9 @@ static int handle_alias(int *argcp, const char ***argv)
/* insert after command name */
memcpy(new_argv + count, *argv + 1, sizeof(char *) * *argcp);

trace2_cmd_alias(alias_command, new_argv);
trace2_cmd_list_config();

*argv = new_argv;
*argcp += count - 1;

Expand Down Expand Up @@ -417,6 +430,8 @@ static int run_builtin(struct cmd_struct *p, int argc, const char **argv)
setup_work_tree();

trace_argv_printf(argv, "trace: built-in: git");
trace2_cmd_name(p->cmd);
trace2_cmd_list_config();

validate_cache_entries(&the_index);
status = p->fn(argc, argv, prefix);
Expand Down Expand Up @@ -666,7 +681,14 @@ static void execv_dashed_external(const char **argv)
cmd.clean_on_exit = 1;
cmd.wait_after_clean = 1;
cmd.silent_exec_failure = 1;
cmd.trace2_child_class = "dashed";

trace2_cmd_name("_run_dashed_");

/*
* The code in run_command() logs trace2 child_start/child_exit
* events, so we do not need to report exec/exec_result events here.
*/
trace_argv_printf(cmd.args.argv, "trace: exec:");

/*
Expand All @@ -676,6 +698,12 @@ static void execv_dashed_external(const char **argv)
* the program.
*/
status = run_command(&cmd);

/*
* If the child process ran and we are now going to exit, emit a
* generic string as our trace2 command verb to indicate that we
* launched a dashed command.
*/
if (status >= 0)
exit(status);
else if (errno != ENOENT)
Expand All @@ -701,6 +729,43 @@ static int run_argv(int *argcp, const char ***argv)
if (!done_alias)
handle_builtin(*argcp, *argv);

#if 0 // TODO In GFW, need to amend a7924b655e940b06cb547c235d6bed9767929673 to include trace2_ and _tr2 lines.
else if (get_builtin(**argv)) {
struct argv_array args = ARGV_ARRAY_INIT;
int i;

/*
* The current process is committed to launching a
* child process to run the command named in (**argv)
* and exiting. Log a generic string as the trace2
* command verb to indicate this. Note that the child
* process will log the actual verb when it runs.
*/
trace2_cmd_name("_run_git_alias_");

if (get_super_prefix())
die("%s doesn't support --super-prefix", **argv);

commit_pager_choice();

argv_array_push(&args, "git");
for (i = 0; i < *argcp; i++)
argv_array_push(&args, (*argv)[i]);

trace_argv_printf(args.argv, "trace: exec:");

/*
* if we fail because the command is not found, it is
* OK to return. Otherwise, we just pass along the status code.
*/
i = run_command_v_opt_tr2(args.argv, RUN_SILENT_EXEC_FAILURE |
RUN_CLEAN_ON_EXIT, "git_alias");
if (i >= 0 || errno != ENOENT)
exit(i);
die("could not execute builtin %s", **argv);
}
#endif // a7924b655e940b06cb547c235d6bed9767929673

/* .. then try the external ones */
execv_dashed_external(*argv);

Expand Down
7 changes: 7 additions & 0 deletions remote-curl.c
Original file line number Diff line number Diff line change
Expand Up @@ -1360,6 +1360,13 @@ int cmd_main(int argc, const char **argv)
string_list_init(&options.deepen_not, 1);
string_list_init(&options.push_options, 1);

/*
* Just report "remote-curl" here (folding all the various aliases
* ("git-remote-http", "git-remote-https", and etc.) here since they
* are all just copies of the same actual executable.
*/
trace2_cmd_name("remote-curl");

remote = remote_get(argv[1]);

if (argc > 2) {
Expand Down
2 changes: 2 additions & 0 deletions repository.c
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,8 @@ static int repo_init_gitdir(struct repository *repo, const char *gitdir)
void repo_set_worktree(struct repository *repo, const char *path)
{
repo->worktree = real_pathdup(path, 1);

trace2_def_repo(repo);
}

static int read_and_verify_repository_format(struct repository_format *format,
Expand Down
3 changes: 3 additions & 0 deletions repository.h
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,9 @@ struct repository {
/* Repository's current hash algorithm, as serialized on disk. */
const struct git_hash_algo *hash_algo;

/* A unique-id for tracing purposes. */
int trace2_repo_id;

/* Configurations */

/* Indicate if a repository has a different 'commondir' from 'gitdir' */
Expand Down
Loading