// Copyright Earl Warren // Copyright Loïc Dachary // SPDX-License-Identifier: MIT package repository import ( "context" "fmt" "os" "strings" "code.forgejo.org/f3/gof3/v3/logger" "code.forgejo.org/f3/gof3/v3/util" ) func GitGetSha(ctx context.Context, log logger.MessageInterface, repo, ref string) string { sha := util.Command(ctx, log, "git", "-C", repo, "rev-parse", ref) return strings.TrimSuffix(sha, "\n") } func disableHooks(ctx context.Context, log logger.MessageInterface, dir string) func() { if !util.FileExists(dir) { return func() {} } util.Command(ctx, log, "git", "-C", dir, "config", "core.hooksPath", "/dev/null") return func() { util.Command(ctx, log, "git", "-C", dir, "config", "--unset", "core.hooksPath") } } func GitMirrorRef(ctx context.Context, log logger.MessageInterface, originURL, originRef, destinationURL, destinationRef string) { if log == nil { log = logger.NewLogger() } if originURL == destinationURL { log.Log(1, logger.Trace, "do nothing because origin & destination are the same %s\n", originURL) return } log.Log(1, logger.Trace, "%s:%s => %s:%s\n", originURL, originRef, destinationURL, destinationRef) defer disableHooks(ctx, log, destinationURL)() if util.FileExists(originURL) { util.Command(ctx, log, "git", "-C", originURL, "push", destinationURL, "+"+originRef+":"+destinationRef) } else { if util.FileExists(destinationURL) { util.Command(ctx, log, "git", "-C", destinationURL, "fetch", originURL, "+"+originRef+":"+destinationRef) } else { directory, err := os.MkdirTemp("", "driverRepository") if err != nil { panic(err) } defer func() { err := os.RemoveAll(directory) if err != nil { panic(err) } }() util.Command(ctx, log, "git", "clone", "--bare", "--depth", "1", originURL, directory) util.Command(ctx, log, "git", "-C", directory, "fetch", "origin", originRef) util.Command(ctx, log, "git", "-C", directory, "push", destinationURL, "+FETCH_HEAD:"+destinationRef) } } } func GitMirror(ctx context.Context, log logger.MessageInterface, origin, destination string, internalRefs []string) { if log == nil { log = logger.NewLogger() } if origin == destination { log.Log(1, logger.Trace, "do nothing because origin & destination are the same %s\n", origin) return } log.Log(1, logger.Trace, "%s => %s\n", origin, destination) defer disableHooks(ctx, log, destination)() excludeInternalRefs := make([]string, 0, len(internalRefs)) for _, ref := range internalRefs { excludeInternalRefs = append(excludeInternalRefs, fmt.Sprintf("^%s", ref)) } if util.FileExists(origin) { args := append([]string{"-C", origin, "push", destination, "+refs/*:refs/*"}, excludeInternalRefs...) util.Command(ctx, log, "git", args...) } else { if util.FileExists(destination) { util.Command(ctx, log, "git", "-C", destination, "remote", "add", "--mirror=fetch", "fetchMirror", origin) defer func() { util.Command(ctx, log, "git", "-C", destination, "remote", "remove", "fetchMirror") }() util.Command(ctx, log, "git", "-C", destination, "fetch", "fetchMirror") } else { directory, err := os.MkdirTemp("", "driverRepository") if err != nil { panic(err) } defer func() { err := os.RemoveAll(directory) if err != nil { panic(err) } }() util.Command(ctx, log, "git", "clone", "--mirror", origin, directory) args := append([]string{"-C", directory, "push", destination, "+refs/*:refs/*"}, excludeInternalRefs...) util.Command(ctx, log, "git", args...) } } }