Subject: [RFC PATCH 0/2] MVP implementation of remote-suggested hooks

From: Jonathan Tan <[email-masked]>
Date: Wed, 16 Jun 2021 16:31:47 -0700

This is a continuation of the work from [1]. That work described the
reasons, possible features, and possible workflows, but not the
implementation in detail. This patch set has an MVP implementation, and
my hope is that having a concrete implementation to look at makes it
easier to discuss matters of implementation.

This but does not use any features from es/config-based-hooks but is
implemented on that branch anyway because firstly, I need an existing
command to attach the "autoupdate" subcommand (and "git hook" works),
and secondly, when we test this at $DAYJOB, we will be testing it
together with the aforementioned branch.

I have had to make several design choices (which I will discuss later),
but now with this implementation, the following workflow is possible:

 1. The remote repo administrator creates a new branch
    "refs/heads/suggested-hooks" pointing to a commit that has all the
    hooks that the administrator wants to suggest. The hooks are
    directly referenced by the commit tree (i.e. they are in the "/"
    directory).

 2. When a user clones, Git notices that
    "refs/remotes/origin/suggested-hooks" is present and prints out a
    message about a command that can be run.

 3. If the user runs that command, Git will install the hooks pointed to
    by that ref, and set hook.autoupdate to true. This config variable
    is checked whenever "git fetch" is run: whenever it notices that
    "refs/remotes/origin/suggested-hooks" changes, it will reinstall the
    hooks.

 4. To turn off autoupdate, set hook.autoupdate to false. Existing hooks
    will remain.

Design choices:

 1. Where should the suggested hooks be in the remote repo? A branch,
    a non-branch ref, a config? I think that a branch is best - it is
    relatively well-understood and any hooks there can be
    version-controlled (and its history is independent of the other
    branches).

 2. When and how should the local repo update its record of the remote's
    suggested hooks? If we go with storing the hooks in a branch of a
    remote side, this would automatically mean (with the default
    refspec) that it would be in refs/remotes/<remote>/<name>. This
    incurs network and hard disk cost even if the local repo does not
    want to use the suggested hooks, but I think that typically they
    would want to use it if they're going to do any work on the repo
    (they would either have to trust or inspect Makefiles etc. anyway,
    so they can do the same for the hooks), and even if they don't want
    to use the remote's hooks, they probably still want to know what the
    remote suggests.

    So using a branch provides a well-understood way of storing the
    hooks on the remote, transmitting it to the local repo, and storing
    the hooks in the local repo.

    So: what should be the default name of this branch? Presumably, "git
    clone" would need to be able to override this.

 3. How should the local repo detect when the remote has updated its
    suggested hooks? I'm thinking when a certain local ref is updated.
    Right now it's hardcoded, but perhaps "git clone" could detect what
    "refs/heads/suggested-hooks" would correspond to, and then set it in
    a config accordingly. Other options include remembering what the
    remote's "refs/heads/suggested-hooks" used to be and always
    comparing it upon every "ls-refs" call, but I think that the local
    ref method is more straightforward.

 4. Should the local repo try to notice if the hooks have been changed
    locally before overwriting upon autoupdate? This would be nice to
    have, but I don't know how practical it would be. In particular, I
    don't know if we can trust that
    "refs/remotes/origin/suggested-hooks" has not been clobbered.

 5. Should we have a command that manually updates the hooks with what's
    in "refs/heads/suggested-hooks"? This is not in this patch set, but
    it sounds like a good idea.

There are perhaps other points that I haven't thought of, of course.

[1] https://lore.kernel.org/git/[email-masked]/

Jonathan Tan (2):
  hook: move list of hooks
  clone,fetch: remote-suggested auto-updating hooks

 builtin/bugreport.c |  38 ++------------
 builtin/clone.c     |  10 ++++
 builtin/fetch.c     |  21 ++++++++
 builtin/hook.c      |  13 +++--
 hook.c              | 118 ++++++++++++++++++++++++++++++++++++++++++++
 hook.h              |   5 ++
 t/t5601-clone.sh    |  36 ++++++++++++++
 7 files changed, 202 insertions(+), 39 deletions(-)

-- 
2.32.0.272.g935e593368-goog