112 lines
2.1 KiB
Go
112 lines
2.1 KiB
Go
package git
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
|
|
"github.com/go-git/go-git/v6"
|
|
"github.com/go-git/go-git/v6/config"
|
|
"github.com/go-git/go-git/v6/plumbing/transport"
|
|
"github.com/go-git/go-git/v6/plumbing/transport/http"
|
|
"github.com/go-git/go-git/v6/storage/memory"
|
|
)
|
|
|
|
type (
|
|
Repository struct {
|
|
src string
|
|
dst string
|
|
srcAuth Authentication
|
|
dstAuth Authentication
|
|
}
|
|
|
|
Authentication interface {
|
|
Value() transport.AuthMethod
|
|
}
|
|
|
|
TokenAuthentication struct {
|
|
token string
|
|
}
|
|
|
|
BasicAuthentication struct {
|
|
username, password string
|
|
}
|
|
|
|
NoAuthentication struct{}
|
|
)
|
|
|
|
func NewRepository(src, dst string, srcAuth, dstAuth Authentication) Repository {
|
|
return Repository{
|
|
src: src,
|
|
dst: dst,
|
|
srcAuth: srcAuth,
|
|
dstAuth: dstAuth,
|
|
}
|
|
}
|
|
|
|
func NewTokenAuthentication(token string) TokenAuthentication {
|
|
return TokenAuthentication{
|
|
token: token,
|
|
}
|
|
}
|
|
|
|
func NewBasicAuthentication(username, password string) BasicAuthentication {
|
|
return BasicAuthentication{
|
|
username: username,
|
|
password: password,
|
|
}
|
|
}
|
|
|
|
func Sync(r Repository) error {
|
|
repo, err := git.Clone(memory.NewStorage(), nil, &git.CloneOptions{
|
|
URL: r.src,
|
|
Auth: r.srcAuth.Value(),
|
|
})
|
|
if err != nil {
|
|
return fmt.Errorf("failed to clone repository from source: %w", err)
|
|
}
|
|
|
|
m, err := repo.CreateRemote(&config.RemoteConfig{
|
|
Name: "mirror",
|
|
Mirror: true,
|
|
URLs: []string{
|
|
r.dst,
|
|
},
|
|
})
|
|
if err != nil {
|
|
return fmt.Errorf("failed to create remote: %w", err)
|
|
}
|
|
|
|
err = m.Push(&git.PushOptions{
|
|
RemoteName: "mirror",
|
|
Auth: r.dstAuth.Value(),
|
|
RefSpecs: []config.RefSpec{"+refs/*:refs/*"},
|
|
Force: true,
|
|
})
|
|
if err != nil {
|
|
if errors.Is(err, git.NoErrAlreadyUpToDate) {
|
|
return nil
|
|
}
|
|
return fmt.Errorf("failed to push to mirror server: %w", err)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (a TokenAuthentication) Value() transport.AuthMethod {
|
|
return &http.BasicAuth{
|
|
Username: "git",
|
|
Password: a.token,
|
|
}
|
|
}
|
|
|
|
func (a BasicAuthentication) Value() transport.AuthMethod {
|
|
return &http.BasicAuth{
|
|
Username: a.username,
|
|
Password: a.password,
|
|
}
|
|
}
|
|
|
|
func (NoAuthentication) Value() transport.AuthMethod {
|
|
return nil
|
|
}
|