1 Star 0 Fork 0

h79/goutils

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
api
auth
common
algorithm
app
attributes
banner
bus
coder
compress
config
daemon
data
debug
file
filemgr
git
git.go
http
images
json
list
logger
mapper
perf
queue
random
result
scheduler
secret
server
ssh
stringutil
svc
system
template
timer
trie
version
xml
bit_flag.go
common.go
common_test.go
integer.go
recover.go
dao
discovery
loader
mq
pay
plugins
report
request
rpc
sensitive
thrift
.gitignore
LICENSE
Makefile
README.md
doc.go
error.md
go.mod
go.sum
goutils.go
goutils_test.go
version.go
克隆/下载
git.go 7.73 KB
一键复制 编辑 原始数据 按行查看 历史
huqiuyun 提交于 2年前 . rpc ,close connect,git
package git
import (
"crypto/tls"
"errors"
"gitee.com/h79/goutils/common/file"
"gitee.com/h79/goutils/common/random"
"net/http"
"os"
"path/filepath"
"strings"
"time"
"bytes"
"log"
"os/exec"
"runtime"
"golang.org/x/crypto/ssh"
"gopkg.in/src-d/go-git.v4"
"gopkg.in/src-d/go-git.v4/config"
"gopkg.in/src-d/go-git.v4/plumbing"
"gopkg.in/src-d/go-git.v4/plumbing/object"
"gopkg.in/src-d/go-git.v4/plumbing/transport"
"gopkg.in/src-d/go-git.v4/plumbing/transport/client"
githttp "gopkg.in/src-d/go-git.v4/plumbing/transport/http"
gitssh "gopkg.in/src-d/go-git.v4/plumbing/transport/ssh"
)
const branchNamePrefix = "refs/heads/auto-"
type Git struct {
Url string `json:"url"`
SshKey string `json:"ssh_key"`
SshKeySalt string `json:"ssh_key_salt"`
Path string `json:"path"`
Branch string `json:"branch"`
Username string `json:"username"`
Password string `json:"password"`
DirUser string `json:"dir_user"`
}
func (g *Git) Validate() error {
if g.Path == "" {
return errors.New("git path param error")
}
if g.Url == "" {
return errors.New("git url param error")
}
if g.IsHTTP() {
if (g.Username != "" && g.Password == "") ||
(g.Username == "" && g.Password != "") {
return errors.New("git param username and password error")
}
} else if g.SshKey == "" {
return errors.New("git ssh_key param error")
}
return nil
}
func (g *Git) Checkout(name string) (err error) {
r, err := git.PlainOpen(g.Path)
if err != nil {
return
}
w, err := r.Worktree()
if err != nil {
return
}
err = w.Checkout(&git.CheckoutOptions{
Branch: plumbing.ReferenceName("refs/heads/" + name),
Force: true,
})
return
}
func (g *Git) CleanBranch() (err error) {
//var hash string
//var hashObj plumbing.Hash
var r *git.Repository
//var ref *plumbing.Reference
if r, err = git.PlainOpen(g.Path); err != nil {
return
}
refs, err := r.References()
if err != nil {
return
}
h, err := r.Head()
if err != nil {
return
}
headBranchName := h.Name().String()
err = refs.ForEach(func(ref0 *plumbing.Reference) (e error) {
if headBranchName != ref0.Name().String() && strings.HasPrefix(ref0.Name().String(), "refs/heads/") {
e = r.Storer.RemoveReference(ref0.Name())
return
}
return nil
})
return
}
func (g *Git) CreateBranchName() (name string, err error) {
var hash string
// var hashObj plumbing.Hash
var ref *plumbing.Reference
hash, _, _, ref, err = g.GetHash()
if err != nil {
return
}
f := ""
if ref != nil {
f = filepath.Base(ref.Name().Short())
} else {
f = hash
}
name = branchNamePrefix + f + "-" + random.GenerateString(8)
return
}
func (g *Git) Publish() (commitId string, err error) {
defer func() {
go func() {
if runtime.GOOS != "windows" {
cmd := exec.Command("chown", "-R", g.DirUser, g.Path)
var out bytes.Buffer
cmd.Stderr = &out
err = cmd.Run()
if err != nil {
log.Println(out.String())
}
}
}()
}()
if file.DirEmpty(g.Path) {
err = nil
_, err = g.Clone()
} else {
p := filepath.Join(g.Path, ".git")
if _, err := os.Stat(p); err != nil || file.DirEmpty(p) {
return "", errors.New("git: publish error, target path is not a git repository")
}
_, err = git.PlainOpen(g.Path)
if err == nil {
_, err = g.Fetch()
}
}
if err != nil {
return
}
branchShortName := ""
branchShortName, _, err = g.CreateBranch()
if err != nil {
return
}
//output := ""
err = g.Checkout(branchShortName)
if err != nil {
return
}
err = g.CleanBranch()
if err != nil {
return
}
// get commit_id
commitId, err = g.LastCommitId()
return
}
// 创建分支
func (g *Git) CreateBranch() (branchShortName, branchName string, err error) {
_, hashObj, r, _, err := g.GetHash()
if err != nil {
return
}
branchName, err = g.CreateBranchName()
if err != nil {
return
}
branchShortName = filepath.Base(branchName)
err = r.Storer.SetReference(plumbing.NewHashReference(plumbing.ReferenceName(branchName), hashObj))
return
}
// 获取 hash
func (g *Git) GetHash() (hash string, hashObj plumbing.Hash, r *git.Repository, ref *plumbing.Reference, err error) {
if r, err = git.PlainOpen(g.Path); err != nil {
return
}
refs, err := r.References()
if err != nil {
return
}
refs.ForEach(func(ref0 *plumbing.Reference) (e error) {
//fmt.Println(ref0.Name().String(), ref0.Hash().String())
if !strings.HasPrefix(ref0.Name().String(), "refs/heads/") {
if g.Branch == filepath.Base(ref0.Name().String()) {
hash = ref0.Hash().String()
ref = ref0
hashObj = ref0.Hash()
return errors.New("")
}
}
return nil
})
if hash == "" {
var c *object.Commit
c, err = r.CommitObject(plumbing.NewHash(g.Branch))
if err == nil {
hash = g.Branch
hashObj = c.Hash
return
}
}
return
}
// 拉取代码
func (g *Git) Fetch() (r *git.Repository, err error) {
if err = g.Validate(); err != nil {
return
}
if r, err = git.PlainOpen(g.Path); err != nil {
return
}
rconfig, err := r.Storer.Config()
if err != nil {
return
}
remoteConfig := &config.RemoteConfig{
Name: git.DefaultRemoteName,
URLs: []string{g.Url},
Fetch: []config.RefSpec{"+refs/heads/*:refs/remotes/" + git.DefaultRemoteName + "/*"},
}
rconfig.Remotes = map[string]*config.RemoteConfig{
git.DefaultRemoteName: remoteConfig,
}
err = r.Storer.SetConfig(rconfig)
if err != nil {
return
}
var opt git.FetchOptions
if opt, err = g.FetchOptions(); err != nil {
return
}
if err = r.Fetch(&opt); err == git.NoErrAlreadyUpToDate {
err = nil
}
return
}
func (g *Git) Clone() (r *git.Repository, err error) {
if err = g.Validate(); err != nil {
return
}
var opt git.CloneOptions
opt, err = g.CloneOptions()
if err != nil {
return
}
r, err = git.PlainClone(g.Path, false, &opt)
return
}
func (g *Git) LastCommitId() (hash string, err error) {
if err = g.Validate(); err != nil {
return
}
var r *git.Repository
if r, err = git.PlainOpen(g.Path); err != nil {
return
}
commitIter, err := r.Log(&git.LogOptions{})
if err != nil {
return
}
commit, err := commitIter.Next()
if err != nil {
return
}
hash = commit.Hash.String()
return
}
func (g *Git) CloneOptions() (opt git.CloneOptions, err error) {
opt.URL = g.Url
if g.IsNeedAuth() {
opt.Auth, err = g.GetAuth()
if err != nil {
return
}
}
return
}
func (g *Git) FetchOptions() (opt git.FetchOptions, err error) {
opt.RemoteName = git.DefaultRemoteName
opt.RefSpecs = []config.RefSpec{"+refs/heads/*:refs/remotes/" + git.DefaultRemoteName + "/*"}
if g.IsNeedAuth() {
opt.Auth, err = g.GetAuth()
if err != nil {
return
}
}
return
}
func (g *Git) GetAuth() (auth transport.AuthMethod, err error) {
var signer ssh.Signer
if g.IsHTTP() {
customClient := &http.Client{
Transport: &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
},
Timeout: 30 * time.Minute,
CheckRedirect: func(req *http.Request, via []*http.Request) error {
return http.ErrUseLastResponse
},
}
client.InstallProtocol("https", githttp.NewClient(customClient))
client.InstallProtocol("http", githttp.NewClient(customClient))
auth = &githttp.BasicAuth{
Username: g.Username,
Password: g.Password,
}
} else {
if g.SshKeySalt != "" {
signer, err = ssh.ParsePrivateKeyWithPassphrase([]byte(g.SshKey), []byte(g.SshKeySalt))
} else {
signer, err = ssh.ParsePrivateKey([]byte(g.SshKey))
}
if err != nil {
return
}
auth = &gitssh.PublicKeys{
User: "git",
Signer: signer,
HostKeyCallbackHelper: gitssh.HostKeyCallbackHelper{
HostKeyCallback: ssh.InsecureIgnoreHostKey(),
},
}
}
return
}
func (g *Git) IsHTTP() bool {
return strings.HasPrefix(g.Url, "http://") || strings.HasPrefix(g.Url, "https://")
}
func (g *Git) IsNeedAuth() bool {
if g.IsHTTP() {
return g.Username != "" && g.Password != ""
}
return g.SshKey != ""
}
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
Go
1
https://gitee.com/h79/goutils.git
git@gitee.com:h79/goutils.git
h79
goutils
goutils
v1.3.48

搜索帮助