fix(lfs): fetch missing lfs objects when mirroring

Ayman Bagabas created

Ensure to pull the latest lfs objects when mirroring a repository with
lfs enabled.

Change summary

server/jobs/mirror.go | 38 ++++++++++++++++++++++++++++++++++++++
1 file changed, 38 insertions(+)

Detailed changes

server/jobs/mirror.go 🔗

@@ -10,6 +10,9 @@ import (
 	"github.com/charmbracelet/soft-serve/git"
 	"github.com/charmbracelet/soft-serve/server/backend"
 	"github.com/charmbracelet/soft-serve/server/config"
+	"github.com/charmbracelet/soft-serve/server/db"
+	"github.com/charmbracelet/soft-serve/server/lfs"
+	"github.com/charmbracelet/soft-serve/server/store"
 	"github.com/charmbracelet/soft-serve/server/sync"
 )
 
@@ -22,6 +25,8 @@ func mirrorPull(ctx context.Context) func() {
 	cfg := config.FromContext(ctx)
 	logger := log.FromContext(ctx).WithPrefix("jobs.mirror")
 	b := backend.FromContext(ctx)
+	dbx := db.FromContext(ctx)
+	datastore := store.FromContext(ctx)
 	return func() {
 		repos, err := b.Repositories(ctx)
 		if err != nil {
@@ -45,6 +50,7 @@ func mirrorPull(ctx context.Context) func() {
 
 				name := repo.Name()
 				wq.Add(name, func() {
+					repo := repo
 					cmd := git.NewCommand("remote", "update", "--prune").WithContext(ctx)
 					cmd.AddEnvs(
 						fmt.Sprintf(`GIT_SSH_COMMAND=ssh -o UserKnownHostsFile="%s" -o StrictHostKeyChecking=no -i "%s"`,
@@ -56,6 +62,38 @@ func mirrorPull(ctx context.Context) func() {
 					if _, err := cmd.RunInDir(r.Path); err != nil {
 						logger.Error("error running git remote update", "repo", name, "err", err)
 					}
+
+					if cfg.LFS.Enabled {
+						rcfg, err := r.Config()
+						if err != nil {
+							logger.Error("error getting git config", "repo", name, "err", err)
+							return
+						}
+
+						lfsEndpoint := rcfg.Section("lfs").Option("url")
+						if lfsEndpoint == "" {
+							// If there is no LFS url defined, means the repo
+							// doesn't use LFS and we can skip it.
+							return
+						}
+
+						ep, err := lfs.NewEndpoint(lfsEndpoint)
+						if err != nil {
+							logger.Error("error creating LFS endpoint", "repo", name, "err", err)
+							return
+						}
+
+						client := lfs.NewClient(ep)
+						if client == nil {
+							logger.Errorf("failed to create lfs client: unsupported endpoint %s", lfsEndpoint)
+							return
+						}
+
+						if err := backend.StoreRepoMissingLFSObjects(ctx, repo, dbx, datastore, client); err != nil {
+							logger.Error("failed to store missing lfs objects", "err", err, "path", r.Path)
+							return
+						}
+					}
 				})
 			}
 		}