Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Push equivalent to clone mirror? #927

Open
Marakai opened this issue Aug 29, 2022 · 1 comment
Open

Push equivalent to clone mirror? #927

Marakai opened this issue Aug 29, 2022 · 1 comment

Comments

@Marakai
Copy link

Marakai commented Aug 29, 2022

Despite looking at the godocs, the tests and the source, I can't seem to figure out the correction PushOptions for the opposite of a mirror clone, i.e. push with the mirror options. Ideally, for my special use case with force.

I'm trying to clone from one server and push to another, using the mirror option. So, I:

  • mirror clone with a code example I found here in Issues
  • create a new remote pointing to the other server (the repo was already created separately)
  • ??? what pushoptions for mirror ???
  • push to the new repo on other server

This is using https, not ssh, if it matters.

On that notice, more examples would be very nice (looking at unit tests isn't quite the sames thing).

@Marakai
Copy link
Author

Marakai commented Aug 30, 2022

At this time, my somewhat naive first implementation, after poring through the source looks like this. However there are a number of issues that I've listed with inline comments.

Note: this is built on MacOS. libgit2, libssh2 and openssl are installed via Homebrew. SSL certificates and CA are all installed as part of the corporate build. HTTPS pushes into Git are authenticated via access token.

package migrate

import (
	"XXXXXX.ghe.com/gh-platform/gh-management-services/service/api"
	gitwrap "XXXXXXX.ghe.com/gh-platform/gh-management-services/service/utils/git"
	"context"
	"errors"
	libgit "github.com/libgit2/git2go/v33"
)

const GHAE = "XXXXXXX.ghe.com"

func MirrorPush(ctx context.Context, github api.Github, org string, repoSlug string, repo *libgit.Repository) error {
	if ghUrl, err := github.GetRepoUrl(org, repoSlug); err != nil {
		return err
	} else {
		rcb := libgit.RemoteCallbacks{
// This will not be called if I inject the token directly below. However, when called
// I don't get a valid Credential and receive an error 
// "could not find appropriate mechanism for credentials" 
// when Push() is called below.
			CredentialsCallback: func(url, username string, allowedTypes libgit.CredentialType) (*libgit.Credential, error) {
				c, err := libgit.NewCredentialUsername(github.Token())
				if err != nil {
					return nil, err
				}
				return c, nil
			},
			CertificateCheckCallback: func(cert *libgit.Certificate, valid bool, hostname string) error {
				if hostname != GHAE {
					return errors.New("hostname does not match")
				}
				return nil
			},
		}
		proxyopt := libgit.ProxyOptions{
			Type: libgit.ProxyTypeAuto,
			// Url: utils.GetProxyUrl(),
		}
		pushopts := libgit.PushOptions{
			RemoteCallbacks: rcb,
			PbParallelism:   0,
			Headers:         nil,
			ProxyOptions:    proxyopt,
		}

		logger.Notice(ctx, "starting push of %s into %s", repoSlug, ghUrl)
		remote, err := repo.Remotes.CreateWithFetchspec("ghorigin", ghUrl, "+refs/*:refs/*")
		if err != nil {
			return err
		}
// A helper method to inject the access token during debugging and testing
// It retrieves the token from a secure store
// When injecting the token into the URL, the connection succeeds, but this is highly
// undesirable due to risk of exposure
		ghUrl = gitwrap.InjectToken(ghUrl, github.Token())

		cfg, err := repo.Config()
		if err != nil {
			return err
		}

		if err = cfg.SetBool("remote.ghorigin.mirror", true); err != nil {
			return err
		}

// When using the injected URL and able to connect, this call returns without error
// But does NOT actually push anything!
		if err = remote.Push(nil, &pushopts); err != nil {
			return err
		}
		logger.Notice(ctx, "finished mirror-push of %s into %s", repoSlug, repo.Path())
	}
	return nil
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant