checkout: move post_checkout_hook() to checkout.c

post_checkout_hook() in builtin/checkout.c runs the 'post-checkout' hook
after switching branches or checking out paths.

Move post_checkout_hook() to checkout.c and declare it in checkout.h
so that other subsystems can invoke the post-checkout hook without
depending on builtin/checkout.c.

Remove the dependency on 'the_repository'.  While OK when the helper
was in builtin/checkout.c as an integral part of 'git checkout' (and
'git restore'), this is no longer true for a common utility
function.  Have it take a pointer to 'struct repository' and use its
associated hash algorithm.

This step in the series is entirely optional and is here primarily
for illustration.  We may later want to teach 'git worktree' to
trigger the 'post-checkout' hook, for example, in which case such
libification may turn out to be useful.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
seen
Junio C Hamano 2026-08-30 13:48:35 -07:00
parent 3ac7c3315c
commit 5ca19ca0b1
3 changed files with 41 additions and 20 deletions

View File

@ -124,24 +124,6 @@ static void branch_info_release(struct branch_info *info)
free(info->checkout);
}

static int post_checkout_hook(struct commit *old_commit, struct commit *new_commit,
int changed)
{
struct run_hooks_opt opt = RUN_HOOKS_OPT_INIT_FORCE_SERIAL;

/*
* "new_commit" can be NULL when checking out from the index before
* a commit exists.
*/
strvec_pushl(&opt.args,
oid_to_hex(old_commit ? &old_commit->object.oid : null_oid(the_hash_algo)),
oid_to_hex(new_commit ? &new_commit->object.oid : null_oid(the_hash_algo)),
changed ? "1" : "0",
NULL);

return run_hooks_opt(the_repository, "post-checkout", &opt);
}

/*
* Handle a tree object and determine if we need to recurse into the
* tree (READ_TREE_RECURSIVE) or skip it (0).
@ -718,7 +700,7 @@ static int checkout_paths(const struct checkout_opts *opts,
&rev, NULL);
head = lookup_commit_reference_gently(the_repository, &rev, 1);

errs |= post_checkout_hook(head, head, 0);
errs |= post_checkout_hook(the_repository, head, head, 0);
return errs;
}

@ -1273,7 +1255,8 @@ static int switch_branches(const struct checkout_opts *opts,
}
}

ret = post_checkout_hook(old_branch_info.commit, new_branch_info->commit, 1);
ret = post_checkout_hook(the_repository,
old_branch_info.commit, new_branch_info->commit, 1);
branch_info_release(&old_branch_info);
strbuf_release(&old_commit_shortname);
strbuf_release(&autostash_msg);

View File

@ -1,6 +1,9 @@
#define USE_THE_REPOSITORY_VARIABLE

#include "git-compat-util.h"
#include "commit.h"
#include "hex.h"
#include "hook.h"
#include "object-name.h"
#include "remote.h"
#include "refspec.h"
@ -8,6 +11,7 @@
#include "checkout.h"
#include "config.h"
#include "strbuf.h"
#include "strvec.h"

struct tracking_name_data {
/* const */ char *src_ref;
@ -73,3 +77,27 @@ char *unique_tracking_name(const char *name, struct object_id *oid,
}
return NULL;
}

int post_checkout_hook(struct repository *repo,
struct commit *old_commit, struct commit *new_commit,
int changed)
{
struct run_hooks_opt opt = RUN_HOOKS_OPT_INIT_FORCE_SERIAL;
const struct git_hash_algo *hash_algo = repo->hash_algo;

/*
* "new_commit" can be NULL when checking out from the index before
* a commit exists.
*/
strvec_pushl(&opt.args,
oid_to_hex(old_commit
? &old_commit->object.oid
: null_oid(hash_algo)),
oid_to_hex(new_commit ?
&new_commit->object.oid
: null_oid(hash_algo)),
changed ? "1" : "0",
NULL);

return run_hooks_opt(repo, "post-checkout", &opt);
}

View File

@ -3,6 +3,9 @@

#include "hash.h"

struct commit;
struct repository;

/*
* Check if the branch name uniquely matches a branch name on a remote
* tracking branch. Return the name of the remote if such a branch
@ -12,4 +15,11 @@ char *unique_tracking_name(const char *name,
struct object_id *oid,
int *dwim_remotes_matched);

/*
* Run the post-checkout hook.
*/
int post_checkout_hook(struct repository *,
struct commit *old_commit, struct commit *new_commit,
int changed);

#endif /* CHECKOUT_H */