Subject: [PATCH v3 0/3] hide-refs: add hook to force hide refs

From: "Sun Chao via GitGitGadget" <[email-masked]>
Date: Mon, 15 Aug 2022 14:56:21 +0000

Gerrit is implemented by JGit and is known as a centralized workflow system
which supports reference-level access control for repository. If we choose
to work in centralized workflow like what Gerrit provided, reference-level
access control is needed and we might add a reference filter hook hide-refs
to hide the private data.

This hook would be invoked by 'git-receive-pack' and 'git-upload-pack'
during the reference discovery phase, each reference will be filtered with
this hook. The hook executes once with no arguments for each
'git-upload-pack' and 'git-receive-pack' process. Once the hook is invoked,
a version number and server process name ('uploadpack' or 'receive') will
send to it in pkt-line format, followed by a flush-pkt. The hook should
respond with its version number.

During reference discovery phase, each reference will be filtered by this
hook. In the following example, the letter 'G' stands for 'git-receive-pack'
or 'git-upload-pack' and the letter 'H' stands for this hook. The hook
decides if the reference will be hidden or not, it sends result back in
pkt-line format protocol, a response "hide" means the references will hide
to the client and can not fetch its private data even in protocol V2.

            # Version negotiation
            G: PKT-LINE(version=1\0uploadpack)
            G: flush-pkt
            H: PKT-LINE(version=1)
            H: flush-pkt

            # Send reference filter request to hook
            G: PKT-LINE(ref <refname>:<refname_full>)
            G: flush-pkt

            # Receive result from the hook.
            # Case 1: this reference is hidden
            H: PKT-LINE(hide)
            H: flush-pkt

            # Case 2: this reference can be advertised
            H: flush-pkt

To enable the hide-refs hook, we should config hiderefs with force: option,
eg:

            git config --add transfer.hiderefs force:refs/prefix1/
            git config --add uploadpack.hiderefs force:!refs/prefix2/

the hide-refs will be called during reference discovery phase and check each
matched reference, a 'hide' response means the reference will be hidden for
its private data even if allowTipSHA1InWant or allowReachableSHA1InWant are
set to true.

Sun Chao (3):
  hide-refs: add hook to force hide refs
  t1419: add test cases for hide-refs hook
  doc: add documentation for the hide-refs hook

 Documentation/githooks.txt                    |  48 ++++
 Makefile                                      |   1 +
 builtin/receive-pack.c                        |   5 +-
 ls-refs.c                                     |   2 +-
 refs.c                                        | 221 +++++++++++++++++-
 refs.h                                        |   6 +
 serve.c                                       |   2 +
 t/helper/test-hide-refs.c                     | 152 ++++++++++++
 t/helper/test-tool.c                          |   1 +
 t/helper/test-tool.h                          |   1 +
 t/t1419-hide-refs-hook.sh                     | 142 +++++++++++
 t/t1419/common-functions.sh                   |  80 +++++++
 t/t1419/once-0000-abnormal-hide-refs-hook.sh  | 161 +++++++++++++
 ...test-0001-ls-remote-with-hide-refs-hook.sh |  77 ++++++
 ...st-0002-upload-pack-with-hide-refs-hook.sh | 122 ++++++++++
 ...t-0003-receive-pack-with-hide-refs-hook.sh |  87 +++++++
 upload-pack.c                                 |  32 +--
 upload-pack.h                                 |   1 +
 18 files changed, 1111 insertions(+), 30 deletions(-)
 create mode 100644 t/helper/test-hide-refs.c
 create mode 100755 t/t1419-hide-refs-hook.sh
 create mode 100644 t/t1419/common-functions.sh
 create mode 100644 t/t1419/once-0000-abnormal-hide-refs-hook.sh
 create mode 100644 t/t1419/test-0001-ls-remote-with-hide-refs-hook.sh
 create mode 100644 t/t1419/test-0002-upload-pack-with-hide-refs-hook.sh
 create mode 100644 t/t1419/test-0003-receive-pack-with-hide-refs-hook.sh

base-commit: afa70145a25e81faa685dc0b465e52b45d2444bd
Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-git-1301%2Fsunchao9%2Frefs_advertise-v3
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-git-1301/sunchao9/refs_advertise-v3
Pull-Request: https://github.com/git/git/pull/1301

Range-diff vs v2:

 1:  3b8fb63cc78 ! 1:  01c63ea5fee hide-refs: add hook to force hide refs
     @@ Commit message
          `hide-refs` to hide the private data.
      
          This hook would be invoked by 'git-receive-pack' and 'git-upload-pack'
     -    during the reference discovery phase, each reference and will be filtered
     +    during the reference discovery phase, each reference will be filtered
          with this hook. The hook executes once with no arguments for each
          'git-upload-pack' and 'git-receive-pack' process. Once the hook is invoked,
          a version number and server process name ('uploadpack' or 'receive') will
          send to it in pkt-line format, followed by a flush-pkt. The hook should
     -    response with its version number.
     +    respond with its version number.
      
          During reference discovery phase, each reference will be filtered by this
          hook. In the following example, the letter 'G' stands for 'git-receive-pack'
          or 'git-upload-pack' and the letter 'H' stands for this hook. The hook
          decides if the reference will be hidden or not, it sends result back in
     -    pkt-line format protocol, a response "hide" the references will hide
     +    pkt-line format protocol, a response "hide" means the references will hide
          to the client and can not fetch its private data even in protocol V2.
      
                  # Version negotiation
     @@ Commit message
      
          the `hide-refs` will be called during reference discovery phase and
          check each matched reference, a 'hide' response means the reference will
     -    be hidden for its private data and even the `allowTipSHA1InWant` or
     -    `allowReachableSHA1InWant` is set to true.
     +    be hidden for its private data even if `allowTipSHA1InWant` or
     +    `allowReachableSHA1InWant` are set to true.
      
          Signed-off-by: Sun Chao <[email-masked]>
      
 2:  72333c12c3f = 2:  b8a490cb3df t1419: add test cases for hide-refs hook
 3:  e737997eb31 ! 3:  99755b377f0 doc: add documentation for the hide-refs hook
     @@ Metadata
       ## Commit message ##
          doc: add documentation for the hide-refs hook
      
     -    "git upload-pack" or "git recevie-pack" can use "hide-refs"
     +    "git upload-pack" or "git receive-pack" can use "hide-refs"
          hook to filter the references during reference discovery phase.
      
          Signed-off-by: Sun Chao <[email-masked]>

-- 
gitgitgadget