func (l *FileLock) Acquire(ctx context.Context, log ui.Logger) error {
	if l.lock == nil {
		lock := flock.New(l.file)
		gotLock, err := lock.TryLock()
		if err != nil {
			return errors.WithStack(err)
		}
		if !gotLock {
			log.Warnf("%s", "Waiting for a lock at "+l.file)
			ticker := time.NewTicker(l.checkInterval)
			defer ticker.Stop()
			for {
				select {
				case <-ticker.C:
					gotLock, err := lock.TryLock()
					if err != nil {
						return errors.WithStack(err)
					}
					if gotLock {
						l.lock = lock
						l.lockCount = 1
						return nil
					}
				case <-ctx.Done():
					return errors.New("timeout while waiting for the lock")
				}
			}
		}
		l.lock = lock
		l.lockCount = 0
	}
	l.lockCount++
	return nil
}
Acquire takes the lock. For every Acquire, Release needs to be called later.
Returns immediately if this process already holds the lock.
package util
import (
	"context"
	"time"
	"github.com/gofrs/flock"
	"github.com/pkg/errors"
	"github.com/cashapp/hermit/ui"
)
type FileLock struct {
	lock          *flock.Flock
	file          string
	lockCount     int
	checkInterval time.Duration
}
func NewLock(file string, checkInterval time.Duration) *FileLock {
	return &FileLock{file: file, checkInterval: checkInterval}
}