Skip to content
quarry Artifact [f13d03297e]
Login

Artifact [f13d03297e]

Artifact f13d03297e875587b80c855fc4587c4232d974a9cb59f447079069389267c4f2:


package zitcli

import (
	"bytes"
	"context"
	"fmt"
	"os"
	"strings"

	"craftdesign.group/quarry/internal/lease"
)

// GitExport exports the store's new check-ins into the Git repository at
// mirror and pushes trunk to remote's branch, fast-forward only (RFC
// 0022), with env added to the child's environment: the caller names
// the ssh command and its key there. It answers zit's output either
// way, because on a refused push that output is the only account of
// why.
//
// A write: zit records the mirror in the store's config. Unattended
// and ungated like the other writes, so a push is not abandoned because
// a listing was busy; ctx bounds it, and losing the lease ends it.
func (c *Client) GitExport(tok lease.Token, ctx context.Context, mirror, remote, branch string, env []string) (string, error) {
	if err := tok.Err(); err != nil {
		return "", err
	}
	ctx, stop := underLease(ctx, tok)
	defer stop()
	args := []string{"git", "export", mirror, "--autopush", remote, "--push-branch", branch, "--quiet", "-R", c.repo}
	if err := checkArgs(args); err != nil {
		return "", err
	}
	cmd, done := spawnUnattended(ctx, repoName(c.repo), "git-mirror", args...)
	defer done()
	if cmd.Err != nil {
		return "", cmd.Err
	}
	cmd.Env = append(os.Environ(), env...)
	// Bounded as a whole: cancelling (the deadline, a lost lease, a
	// stop) kills git and ssh with zit, and the pipes are closed for
	// them if anything still holds them.
	ownGroup(cmd)
	cmd.WaitDelay = waitDelay
	var out bytes.Buffer
	cmd.Stdout, cmd.Stderr = &out, &out
	if err := cmd.Run(); err != nil {
		return strings.TrimSpace(out.String()), fmt.Errorf("zit git export: %w", err)
	}
	return strings.TrimSpace(out.String()), nil
}