2023-09-23 17:12:35 +02:00
|
|
|
package db_lib
|
2023-02-26 07:22:47 +01:00
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"os"
|
|
|
|
"os/exec"
|
|
|
|
"strings"
|
|
|
|
|
|
|
|
"github.com/ansible-semaphore/semaphore/db"
|
|
|
|
"github.com/ansible-semaphore/semaphore/util"
|
|
|
|
)
|
|
|
|
|
2023-09-23 17:12:35 +02:00
|
|
|
type CmdGitClient struct {
|
|
|
|
keyInstallation db.AccessKeyInstallation
|
|
|
|
}
|
2023-02-26 07:22:47 +01:00
|
|
|
|
|
|
|
func (c CmdGitClient) makeCmd(r GitRepository, targetDir GitRepositoryDirType, args ...string) *exec.Cmd {
|
|
|
|
cmd := exec.Command("git") //nolint: gas
|
|
|
|
|
|
|
|
cmd.Env = os.Environ()
|
|
|
|
cmd.Env = append(cmd.Env, fmt.Sprintln("GIT_TERMINAL_PROMPT=0"))
|
|
|
|
if r.Repository.SSHKey.Type == db.AccessKeySSH {
|
2023-09-23 17:12:35 +02:00
|
|
|
sshCmd := "ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i " + c.keyInstallation.GetPath()
|
2023-02-26 07:22:47 +01:00
|
|
|
if util.Config.SshConfigPath != "" {
|
|
|
|
sshCmd += " -F " + util.Config.SshConfigPath
|
|
|
|
}
|
|
|
|
cmd.Env = append(cmd.Env, fmt.Sprintf("GIT_SSH_COMMAND=%s", sshCmd))
|
|
|
|
}
|
|
|
|
|
|
|
|
switch targetDir {
|
|
|
|
case GitRepositoryTmpDir:
|
|
|
|
cmd.Dir = util.Config.TmpPath
|
|
|
|
case GitRepositoryRepoDir:
|
|
|
|
cmd.Dir = r.GetFullPath()
|
|
|
|
default:
|
|
|
|
panic("unknown Repository directory type")
|
|
|
|
}
|
|
|
|
|
|
|
|
cmd.Args = append(cmd.Args, args...)
|
|
|
|
|
|
|
|
return cmd
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c CmdGitClient) run(r GitRepository, targetDir GitRepositoryDirType, args ...string) error {
|
2023-09-23 17:12:35 +02:00
|
|
|
var err error
|
|
|
|
c.keyInstallation, err = r.Repository.SSHKey.Install(db.AccessKeyRoleGit)
|
|
|
|
|
2023-02-26 07:22:47 +01:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2023-09-23 17:12:35 +02:00
|
|
|
defer c.keyInstallation.Destroy() //nolint: errcheck
|
2023-02-26 07:22:47 +01:00
|
|
|
|
|
|
|
cmd := c.makeCmd(r, targetDir, args...)
|
|
|
|
|
|
|
|
r.Logger.LogCmd(cmd)
|
|
|
|
|
|
|
|
return cmd.Run()
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c CmdGitClient) output(r GitRepository, targetDir GitRepositoryDirType, args ...string) (out string, err error) {
|
2023-09-23 17:12:35 +02:00
|
|
|
c.keyInstallation, err = r.Repository.SSHKey.Install(db.AccessKeyRoleGit)
|
2023-02-26 07:22:47 +01:00
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2023-09-23 17:12:35 +02:00
|
|
|
defer c.keyInstallation.Destroy() //nolint: errcheck
|
2023-02-26 07:22:47 +01:00
|
|
|
|
|
|
|
bytes, err := c.makeCmd(r, targetDir, args...).Output()
|
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
out = strings.Trim(string(bytes), " \n")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c CmdGitClient) Clone(r GitRepository) error {
|
|
|
|
r.Logger.Log("Cloning Repository " + r.Repository.GitURL)
|
|
|
|
|
|
|
|
return c.run(r, GitRepositoryTmpDir,
|
|
|
|
"clone",
|
|
|
|
"--recursive",
|
|
|
|
"--branch",
|
|
|
|
r.Repository.GitBranch,
|
|
|
|
r.Repository.GetGitURL(),
|
|
|
|
r.Repository.GetDirName(r.TemplateID))
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c CmdGitClient) Pull(r GitRepository) error {
|
|
|
|
r.Logger.Log("Updating Repository " + r.Repository.GitURL)
|
|
|
|
|
|
|
|
return c.run(r, GitRepositoryRepoDir, "pull", "origin", r.Repository.GitBranch)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c CmdGitClient) Checkout(r GitRepository, target string) error {
|
|
|
|
r.Logger.Log("Checkout repository to " + target)
|
|
|
|
|
|
|
|
return c.run(r, GitRepositoryRepoDir, "checkout", target)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c CmdGitClient) CanBePulled(r GitRepository) bool {
|
|
|
|
err := c.run(r, GitRepositoryRepoDir, "fetch")
|
|
|
|
if err != nil {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
err = c.run(r, GitRepositoryRepoDir,
|
|
|
|
"merge-base", "--is-ancestor", "HEAD", "origin/"+r.Repository.GitBranch)
|
|
|
|
|
|
|
|
return err == nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c CmdGitClient) GetLastCommitMessage(r GitRepository) (msg string, err error) {
|
|
|
|
r.Logger.Log("Get current commit message")
|
|
|
|
|
|
|
|
msg, err = c.output(r, GitRepositoryRepoDir, "show-branch", "--no-name", "HEAD")
|
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(msg) > 100 {
|
|
|
|
msg = msg[0:100]
|
|
|
|
}
|
|
|
|
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c CmdGitClient) GetLastCommitHash(r GitRepository) (hash string, err error) {
|
|
|
|
r.Logger.Log("Get current commit hash")
|
|
|
|
hash, err = c.output(r, GitRepositoryRepoDir, "rev-parse", "HEAD")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c CmdGitClient) GetLastRemoteCommitHash(r GitRepository) (hash string, err error) {
|
|
|
|
out, err := c.output(r, GitRepositoryTmpDir, "ls-remote", r.Repository.GetGitURL(), r.Repository.GitBranch)
|
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
firstSpaceIndex := strings.IndexAny(out, "\t ")
|
|
|
|
if firstSpaceIndex == -1 {
|
|
|
|
err = fmt.Errorf("can't retreave remote commit hash")
|
|
|
|
}
|
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
hash = out[0:firstSpaceIndex]
|
|
|
|
return
|
|
|
|
}
|