Skip to content
quarry Artifact [efb2c4591b]
Login

Artifact [efb2c4591b]

Artifact efb2c4591b4fe01eaf18dfa710e193bfe497451eede83454894176312923ce67:


//go:build unix

package main

import (
	"log"
	"os"
	"path/filepath"
	"syscall"
)

// gitStoreLock is the file beside a Git mirror's store that a pull holds
// while it may write, and that the nightly backup takes before copying
// the store with zit's import files: zit's import map and an interrupted
// import's records must be copied together with the store, and only
// while no import is writing them.
const gitStoreLock = ".quarry-git.lock"

// lockGitStore takes that lock, waiting for a backup in progress, and
// answers the func that releases it. A lock that cannot be taken is
// logged and not fatal: the pull still runs under the forge's own lock,
// and only a concurrent backup is unprotected.
func lockGitStore(store string) func() {
	f, err := os.OpenFile(filepath.Join(store, gitStoreLock), os.O_RDWR|os.O_CREATE, 0o600)
	if err != nil {
		log.Printf("git store lock %s: %v", store, err)
		return func() {}
	}
	if err := syscall.Flock(int(f.Fd()), syscall.LOCK_EX); err != nil {
		log.Printf("git store lock %s: %v", store, err)
		f.Close()
		return func() {}
	}
	return func() { f.Close() }
}

// freeBytes is the space free to this process on dir's file system.
func freeBytes(dir string) (uint64, bool) {
	var st syscall.Statfs_t
	if err := syscall.Statfs(dir, &st); err != nil {
		return 0, false
	}
	return st.Bavail * uint64(st.Bsize), true
}