server/admin/sync/importer_gitbin.go
Pierre-Olivier Mercier 86748b36c8
All checks were successful
continuous-integration/drone/push Build is passing
sync: Use git reset --hard --recurse-submodule
2022-01-22 08:10:53 +01:00

134 lines
3.8 KiB
Go

//go:build !gitgo
// +build !gitgo
package sync
import (
"bytes"
"errors"
"fmt"
"log"
"os"
"os/exec"
"path"
"strings"
)
// GitImporter implements an Importer, where files to imports are located
// inside a local directory from your filesystem, backed by git (binary).
type GitImporter struct {
li LocalImporter
Remote string
}
func NewGitImporter(li LocalImporter, remote string) GitImporter {
return GitImporter{
li: li,
Remote: remote,
}
}
func (i GitImporter) Id() *string {
cmdshow := exec.Command("git", "-C", i.li.Base, "show")
var outshow bytes.Buffer
cmdshow.Stdout = &outshow
err := cmdshow.Run()
var commit string
if err != nil {
commit = fmt.Sprintf("error (%s)", err.Error())
} else {
commit, err = outshow.ReadString('\n')
if err == nil {
commit = strings.TrimPrefix(commit, "commit ")
} else {
commit = fmt.Sprintf("error (%s)", err.Error())
}
}
return &commit
}
func (i GitImporter) Init() error {
// Check if the directory exists, create it if needed
if err := i.li.Init(); err != nil {
return err
}
// If the directory is empty, clone it
if n, err := countFileInDir(i.li.Base); err != nil {
return err
} else if n == 0 {
log.Println("Please wait while creating the local git repository...")
cmdclone := exec.Command("git", "clone", "--recursive", "--depth", "1", "--shallow-submodules", i.Remote, i.li.Base)
stdout, err := cmdclone.CombinedOutput()
if err != nil {
return fmt.Errorf("%w:\n%s", err, stdout)
}
log.Println("Local git repository successfully cloned")
}
// Check if the .git directory exists, change the origin remote to our
cmdremote := exec.Command("git", "-C", i.li.Base, "remote", "set-url", "origin", i.Remote)
stdout, err := cmdremote.CombinedOutput()
if err != nil {
return fmt.Errorf("%w:\n%s", err, stdout)
}
return nil
}
func (i GitImporter) Sync() error {
log.Println("Synchronizing local git repository...")
cmdfetch := exec.Command("git", "-C", i.li.Base, "fetch", "origin")
stdout, err := cmdfetch.CombinedOutput()
if err != nil {
log.Printf("Git repository fetch failed: %s\n%s", err, stdout)
return fmt.Errorf("%w:\n%s", err, stdout)
}
cmdclean := exec.Command("git", "-C", i.li.Base, "clean", "-xfde", "*_MERGED")
stdout, err = cmdclean.CombinedOutput()
if err != nil {
log.Printf("Local git repository clean failed: %s\n%s", err, stdout)
return fmt.Errorf("%w:\n%s", err, stdout)
}
if _, err := os.Stat(path.Join(i.li.Base, ".gitmodules")); !errors.Is(err, os.ErrNotExist) {
// We have submodules, clean it
cmdsubclean := exec.Command("git", "-C", i.li.Base, "submodule", "foreach", "--recursive", "git", "clean", "-xfde", "*_MERGED")
stdout, err = cmdsubclean.CombinedOutput()
if err != nil {
log.Printf("Local git repository submodules clean failed: %s\n%s", err, stdout)
return fmt.Errorf("%w:\n%s", err, stdout)
}
}
cmdreset := exec.Command("git", "-C", i.li.Base, "reset", "--hard", "--recurse-submodule", "origin/master")
stdout, err = cmdreset.CombinedOutput()
if err != nil {
log.Printf("Local git repository reset failed: %s\n%s", err, stdout)
return fmt.Errorf("%w:\n%s", err, stdout)
}
if _, err := os.Stat(path.Join(i.li.Base, ".gitmodules")); !errors.Is(err, os.ErrNotExist) {
// Treat submodules
cmdsublfs := exec.Command("git", "-C", i.li.Base, "submodule", "foreach", "--recursive", "git", "lfs", "pull")
stdout, err = cmdsublfs.CombinedOutput()
if err != nil {
log.Printf("Local LFS synchronization failed: %s\n%s", err, stdout)
return fmt.Errorf("%w:\n%s", err, stdout)
}
} else {
cmdlfs := exec.Command("git", "-C", i.li.Base, "lfs", "pull")
stdout, err = cmdlfs.CombinedOutput()
if err != nil {
log.Printf("Local LFS synchronization failed: %s\n%s", err, stdout)
return fmt.Errorf("%w:\n%s", err, stdout)
}
}
log.Println("Local git repository synchronized successfully")
return nil
}