goploy/repository/GitRepo.go

224 lines
6.7 KiB
Go
Raw Normal View History

2022-04-09 21:53:37 +08:00
// Copyright 2022 The Goploy Authors. All rights reserved.
// Use of this source code is governed by a GPLv3-style
// license that can be found in the LICENSE file.
2021-08-15 23:27:22 +08:00
package repository
import (
"errors"
2022-01-20 21:40:29 +08:00
"fmt"
2021-08-15 23:27:22 +08:00
"github.com/zhenorzz/goploy/core"
"github.com/zhenorzz/goploy/model"
"github.com/zhenorzz/goploy/utils"
"os"
"strconv"
"strings"
)
2021-11-24 11:05:46 +08:00
type GitRepo struct{}
2022-05-14 18:59:46 +08:00
func (GitRepo) CanRollback() bool {
return true
}
2021-11-24 11:05:46 +08:00
// Ping -
func (GitRepo) Ping(url string) error {
git := utils.GIT{}
if err := git.LsRemote("-h", url); err != nil {
return errors.New(git.Err.String())
}
return nil
2021-08-15 23:27:22 +08:00
}
// Create -
func (GitRepo) Create(projectID int64) error {
srcPath := core.GetProjectPath(projectID)
if _, err := os.Stat(srcPath); err == nil {
return nil
}
project, err := model.Project{ID: projectID}.GetData()
if err != nil {
2022-01-20 21:40:29 +08:00
core.Log(core.ERROR, fmt.Sprintf("The project does not exist, projectID:%d", projectID))
2021-08-15 23:27:22 +08:00
return err
}
if err := os.RemoveAll(srcPath); err != nil {
2022-01-20 21:40:29 +08:00
core.Log(core.ERROR, fmt.Sprintf("The project fail to remove, projectID:%d, error: %s", projectID, err.Error()))
2021-08-15 23:27:22 +08:00
return err
}
git := utils.GIT{}
if err := git.Clone(project.URL, srcPath); err != nil {
2022-01-20 21:40:29 +08:00
core.Log(core.ERROR, fmt.Sprintf("The project fail to initialize, projectID:%d, error:%s, detail:%s", projectID, err.Error(), git.Err.String()))
2021-08-15 23:27:22 +08:00
return err
}
2022-01-20 21:40:29 +08:00
2022-01-27 11:34:47 +08:00
git.Dir = srcPath
2022-01-20 21:40:29 +08:00
if err := git.Current(); err != nil {
core.Log(core.ERROR, fmt.Sprintf("The project fail to get current branch, projectID:%d, error:%s, detail:%s", projectID, err.Error(), git.Err.String()))
return err
}
currentBranch := utils.ClearNewline(git.Output.String())
if project.Branch != currentBranch {
2021-08-15 23:27:22 +08:00
if err := git.Checkout("-b", project.Branch, "origin/"+project.Branch); err != nil {
2022-01-20 21:40:29 +08:00
core.Log(core.ERROR, fmt.Sprintf("The project fail to switch branch, projectID:%d, error:%s, detail:%s", projectID, err.Error(), git.Err.String()))
2021-08-15 23:27:22 +08:00
_ = os.RemoveAll(srcPath)
return err
}
}
2022-01-20 21:40:29 +08:00
core.Log(core.TRACE, fmt.Sprintf("The project success to initialize, projectID:%d", projectID))
2021-08-15 23:27:22 +08:00
return nil
}
func (gitRepo GitRepo) Follow(project model.Project, target string) error {
if err := gitRepo.Create(project.ID); err != nil {
return err
}
git := utils.GIT{Dir: core.GetProjectPath(project.ID)}
core.Log(core.TRACE, "projectID:"+strconv.FormatInt(project.ID, 10)+" git add .")
if err := git.Add("."); err != nil {
core.Log(core.ERROR, err.Error()+", detail: "+git.Err.String())
return errors.New(git.Err.String())
}
core.Log(core.TRACE, "projectID:"+strconv.FormatInt(project.ID, 10)+" git reset --hard")
if err := git.Reset("--hard"); err != nil {
core.Log(core.ERROR, err.Error()+", detail: "+git.Err.String())
return errors.New(git.Err.String())
}
// the length of commit id is 40
if len(target) != 40 {
core.Log(core.TRACE, "projectID:"+strconv.FormatInt(project.ID, 10)+" git fetch")
if err := git.Fetch(); err != nil {
core.Log(core.ERROR, err.Error()+", detail: "+git.Err.String())
return errors.New(git.Err.String())
}
}
core.Log(core.TRACE, "projectID:"+strconv.FormatInt(project.ID, 10)+" git checkout -B goploy "+target)
if err := git.Checkout("-B", "goploy", target); err != nil {
core.Log(core.ERROR, err.Error()+", detail: "+git.Err.String())
return errors.New(git.Err.String())
}
return nil
}
2021-08-19 14:40:42 +08:00
func (GitRepo) RemoteBranchList(url string) ([]string, error) {
git := utils.GIT{}
if err := git.LsRemote("-h", url); err != nil {
return []string{}, errors.New(git.Err.String())
}
var list []string
for _, branchWithSha := range strings.Split(git.Output.String(), "\n") {
if len(branchWithSha) != 0 {
branchWithShaSlice := strings.Fields(branchWithSha)
branchWithHead := branchWithShaSlice[len(branchWithShaSlice)-1]
branchWithHeadSlice := strings.Split(branchWithHead, "/")
list = append(list, branchWithHeadSlice[len(branchWithHeadSlice)-1])
}
}
return list, nil
}
2021-08-16 19:45:07 +08:00
func (GitRepo) BranchList(projectID int64) ([]string, error) {
git := utils.GIT{Dir: core.GetProjectPath(projectID)}
if err := git.Fetch(); err != nil {
2022-01-11 11:10:31 +08:00
return []string{}, errors.New(err.Error() + " detail: " + git.Err.String())
2021-08-16 19:45:07 +08:00
}
if err := git.Branch("-r", "--sort=-committerdate"); err != nil {
2022-01-11 11:10:31 +08:00
return []string{}, errors.New(err.Error() + " detail: " + git.Err.String())
2021-08-16 19:45:07 +08:00
}
rawBranchList := strings.Split(git.Output.String(), "\n")
var list []string
for _, row := range rawBranchList {
branch := strings.Trim(row, " ")
if len(branch) != 0 {
list = append(list, branch)
}
}
return list, nil
}
2021-08-15 23:27:22 +08:00
func (GitRepo) CommitLog(projectID int64, rows int) ([]CommitInfo, error) {
git := utils.GIT{Dir: core.GetProjectPath(projectID)}
if err := git.Log("--stat", "--pretty=format:`start`%H`%an`%at`%s`%d`", "-n", strconv.Itoa(rows)); err != nil {
return []CommitInfo{}, errors.New(git.Err.String())
}
list := parseGITLog(git.Output.String())
return list, nil
}
func (GitRepo) BranchLog(projectID int64, branch string, rows int) ([]CommitInfo, error) {
git := utils.GIT{Dir: core.GetProjectPath(projectID)}
if err := git.Log(branch, "--stat", "--pretty=format:`start`%H`%an`%at`%s`%d`", "-n", strconv.Itoa(rows)); err != nil {
return []CommitInfo{}, errors.New(git.Err.String())
}
list := parseGITLog(git.Output.String())
return list, nil
}
func (GitRepo) TagLog(projectID int64, rows int) ([]CommitInfo, error) {
git := utils.GIT{Dir: core.GetProjectPath(projectID)}
if err := git.Add("."); err != nil {
return []CommitInfo{}, errors.New(git.Err.String())
}
if err := git.Reset("--hard"); err != nil {
return []CommitInfo{}, errors.New(git.Err.String())
}
if err := git.Pull(); err != nil {
return []CommitInfo{}, errors.New(git.Err.String())
}
if err := git.Log("--tags", "-n", strconv.Itoa(rows), "--no-walk", "--stat", "--pretty=format:`start`%H`%an`%at`%s`%d`"); err != nil {
return []CommitInfo{}, errors.New(git.Err.String())
}
list := parseGITLog(git.Output.String())
return list, nil
}
func parseGITLog(rawCommitLog string) []CommitInfo {
unformatCommitList := strings.Split(rawCommitLog, "`start`")
unformatCommitList = unformatCommitList[1:]
var commitList []CommitInfo
for _, commitRow := range unformatCommitList {
commitRowSplit := strings.Split(commitRow, "`")
2021-08-19 14:40:42 +08:00
timestamp, _ := strconv.ParseInt(commitRowSplit[2], 10, 64)
2021-08-15 23:27:22 +08:00
commitList = append(commitList, CommitInfo{
Commit: commitRowSplit[0],
Author: commitRowSplit[1],
Timestamp: timestamp,
Message: commitRowSplit[3],
2022-09-16 11:16:01 +08:00
Tag: extractTag(commitRowSplit[4]),
2021-08-15 23:27:22 +08:00
Diff: strings.Trim(commitRowSplit[5], "\n"),
})
}
return commitList
}
2022-09-16 11:16:01 +08:00
func extractTag(raw string) string {
if len(raw) < 3 {
return ""
}
raw = raw[2 : len(raw)-1]
for _, row := range strings.Split(raw, ",") {
if strings.Contains(row, "tag: ") {
raw = row[5:]
break
}
}
return raw
}