Git Mailing List Archive mirror
 help / color / mirror / Atom feed
From: Guga Figueiredo <gugabfigueiredo@gmail.com>
To: git@vger.kernel.org
Subject: Fwd: "reverse proxy" remote-helper
Date: Mon, 1 Apr 2024 19:37:40 +0200	[thread overview]
Message-ID: <CAEK6H9r7NbPpcTiOk7E8ZTr1W_rfarLmU_yT1etDiCs6BaERVw@mail.gmail.com> (raw)
In-Reply-To: <CAEK6H9o2QQGLQQZ0=C=1CjRGg6UiD_0fv7MwQujv1Sa_v41TAw@mail.gmail.com>

Hello,

I am playing around with git remote helpers trying to write a "reverse
proxy" sort of custom helper to work with a personal server and custom
protocol.
I am doing this because git, natively, already does 99% of the work
that I need, and I would like to avoid reinventing the wheel. I just
want to create a barely customized interface for a custom server.
I know I can achieve this with hooks, but I would rather keep this
configuration out of the repos.

conceptually, the command call flow should be something like this:
```
git <cmd> custom::<repo-url>
└──>git-remote-custom <repo-url> <cmd>
    └──>git <native-remote-helper> <repo-url> <cmd>
```

I have been able to implement a git remote helper in go that works on
locally stored remotes following this article by rovaugn and the git
documentation on helpers.

And have stripped it down to bare essentials to try to invoke the
native/builtin remote-helpers directly:
```go
package main

import (
    "errors"
    "fmt"
    "log"
    "net/url"
    "os"
    "os/exec"
    "regexp"
)

func Main() (er error) {

    if len(os.Args) < 3 {
       return fmt.Errorf("Usage: git-remote-custom remote-name remote-url")
    }

    remoteName := os.Args[1]
    remoteUrl := os.Args[2]

    scheme, err := parseRemoteURL(remoteUrl)
    if err != nil {
       return fmt.Errorf("Invalid remote URL %s: %v", remoteUrl, err)
    }

    // do custom stuff here ...

    // proxy through to native git remote helper
    cmd := exec.Command("git", fmt.Sprintf("remote-%s", scheme),
remoteName, remoteUrl)
    cmd.Stdin = os.Stdin
    cmd.Stdout = os.Stdout
    if err := cmd.Run(); err != nil {
       return err
    }

    return nil
}

func main() {
    if err := Main(); err != nil {
       log.Fatal(err)
    }
}

func parseRemoteURL(remoteUrl string) (string, error) {
    if u, err := url.Parse(remoteUrl); err == nil && u.Scheme != "" {
       return u.Scheme, nil
    }

    // Check for SCP-like SSH URLs first because they don't have a "scheme://"
    scpRe := regexp.MustCompile(`^[a-zA-Z0-9._@/+~-]+@[a-zA-Z0-9._@/+~-]+:[a-zA-Z0-9._@/+~-]+(\.git)?$`)
    if scpRe.MatchString(remoteUrl) {
       return "ssh", nil
    }

    return "", errors.New("invalid Git URL scheme")
}
```

and this worked for http(s):
```
$ GIT_TRACE=1 git clone custom::https://github.com/rovaughn/git-remote-grave.git
11:17:52.117674 git.c:455               trace: built-in: git clone
custom::https://github.com/rovaughn/git-remote-grave.git
Cloning into 'git-remote-grave'...
11:17:52.120021 run-command.c:668       trace: run_command: git
remote-custom origin https://github.com/rovaughn/git-remote-grave.git
11:17:52.121757 git.c:742               trace: exec: git-remote-custom
origin https://github.com/rovaughn/git-remote-grave.git
11:17:52.121792 run-command.c:668       trace: run_command:
git-remote-custom origin
https://github.com/rovaughn/git-remote-grave.git
11:17:52.666930 run-command.c:668       trace: run_command: git
index-pack --stdin -v --fix-thin '--keep=fetch-pack 21547 on pop-os'
--check-self-contained-and-connected
remote: Enumerating objects: 71, done.
11:17:52.669349 git.c:455               trace: built-in: git
index-pack --stdin -v --fix-thin '--keep=fetch-pack 21547 on pop-os'
--check-self-contained-and-connected
remote: Total 71 (delta 0), reused 0 (delta 0), pack-reused 71
Receiving objects: 100% (71/71), 48.92 KiB | 1.11 MiB/s, done.
Resolving deltas: 100% (28/28), done.
11:17:52.716950 run-command.c:668       trace: run_command: git
rev-list --objects --stdin --not --all --quiet --alternate-refs
'--progress=Checking connectivity'
11:17:52.718721 git.c:455               trace: built-in: git rev-list
--objects --stdin --not --all --quiet --alternate-refs
'--progress=Checking connectivity'
```

but `ssh` doesn't have a corresponding remote-ssh helper.

Is there a plug and play way to wrap/proxy the `ssh` protocols in a
similar way with a remote-helper? Or are there better approaches to
achieve this?

Any feedback is appreciated,
Kind regards

Guga

           reply	other threads:[~2024-04-01 17:37 UTC|newest]

Thread overview: expand[flat|nested]  mbox.gz  Atom feed
 [parent not found: <CAEK6H9o2QQGLQQZ0=C=1CjRGg6UiD_0fv7MwQujv1Sa_v41TAw@mail.gmail.com>]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=CAEK6H9r7NbPpcTiOk7E8ZTr1W_rfarLmU_yT1etDiCs6BaERVw@mail.gmail.com \
    --to=gugabfigueiredo@gmail.com \
    --cc=git@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).