package sync import ( "bufio" "os" "github.com/go-git/go-git/v5" "github.com/go-git/go-git/v5/config" ) // GitImporter implements an Importer, where files to imports are located // inside a local directory from your filesystem, backed by git. type GitImporter struct { li LocalImporter Remote string } func NewGitImporter(li LocalImporter, remote string) GitImporter { return GitImporter{ li: li, Remote: remote, } } func (i GitImporter) Kind() string { var gitinfo string r, err := git.PlainOpen(i.li.Base) if err == nil { ref, err := r.Head() if err == nil { gitinfo = ref.Hash().String() } } return "git originated from " + i.Remote + " on " + i.li.Kind() + ", currently on commit " + gitinfo } func countFileInDir(dirname string) (int, error) { files, err := os.ReadDir(dirname) if err != nil { return 0, err } return len(files), nil } 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 { _, err = git.PlainClone(i.li.Base, false, &git.CloneOptions{ URL: i.Remote, RecurseSubmodules: git.DefaultSubmoduleRecursionDepth, }) if err != nil { return err } } // Check if the .git directory exists, change the origin remote to our r, err := git.PlainOpen(i.li.Base) if err != nil { return err } r.DeleteRemote("origin") _, err = r.CreateRemote(&config.RemoteConfig{ Name: "origin", URLs: []string{i.Remote}, }) if err != nil { return err } return nil } func (i GitImporter) Sync() error { r, err := git.PlainOpen(i.li.Base) if err != nil { return err } w, err := r.Worktree() if err != nil { return err } // Perform a git pull --rebase origin/master err = w.Pull(&git.PullOptions{ RemoteName: "origin", Depth: 1, RecurseSubmodules: git.DefaultSubmoduleRecursionDepth, Force: true, }) return err } func (i GitImporter) exists(filename string) bool { return i.li.exists(filename) } func (i GitImporter) toURL(filename string) string { return i.li.toURL(filename) } func (i GitImporter) importFile(URI string, next func(string, string) (interface{}, error)) (interface{}, error) { return i.li.importFile(URI, next) } func (i GitImporter) getFile(filename string, writer *bufio.Writer) error { return i.li.getFile(filename, writer) } func (i GitImporter) listDir(filename string) ([]string, error) { return i.li.listDir(filename) } func (i GitImporter) stat(filename string) (os.FileInfo, error) { return i.li.stat(filename) }