Skip to content
quarry Artifact [fdcf298620]
Login

Artifact [fdcf298620]

Artifact fdcf298620bf9949040221446bbffd079ed41e550861b4ad1a567851556b4464:


package zitcli

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

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

// fossilPushArgs is the whole command line of a Fossil mirror's push.
// The password is not in it: argv is readable by every process on the
// machine, so it travels in ZIT_PASSWORD (see FossilPush).
//
// --once authenticates this push and saves nothing: without it zit
// keeps the derived login in the store and a later pull or push to the
// same remote reuses it, a credential nobody here can see or revoke.
func fossilPushArgs(remote, user string) []string {
	return []string{"push", remote, "--user", user, "--once"}
}

// FossilPush pushes everything the store holds (check-ins, wiki,
// tickets, forum, every branch) to the Fossil server at remote over
// Fossil's sync protocol, logging in as user, with env added to the
// child's environment: the caller puts ZIT_PASSWORD there. It answers
// zit's output either way, because on a refused push that output is the
// only account of why. Fossil sync only adds, so nothing on the remote
// is ever discarded.
//
// Runs in the store directory: zit push, like pull, refuses -R. Under
// the store's lease like the other unattended writes, so a node that
// loses the lease stops pushing; ctx bounds it.
func (c *Client) FossilPush(tok lease.Token, ctx context.Context, remote, user string, env []string) (string, error) {
	if err := tok.Err(); err != nil {
		return "", err
	}
	ctx, stop := underLease(ctx, tok)
	defer stop()
	args := fossilPushArgs(remote, user)
	if err := checkArgs(args); err != nil {
		return "", err
	}
	cmd, done := spawnUnattended(ctx, repoName(c.repo), "fossil-mirror", args...)
	defer done()
	if cmd.Err != nil {
		return "", cmd.Err
	}
	cmd.Dir = c.repo
	cmd.Env = append(os.Environ(), env...)
	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 push: %w", err)
	}
	return strings.TrimSpace(out.String()), nil
}