git.sr.ht/~pingoo/stdx@v0.0.0-20240218134121-094174641f6e/singleinstance/singleinstance.go (about) 1 // Package singleinstance provides a mechanism to ensure, that only one instance of a program is running 2 package singleinstance 3 4 import ( 5 "errors" 6 "fmt" 7 "os" 8 "path/filepath" 9 ) 10 11 // Option configures Single 12 type Option func(*SingleInstance) 13 14 // WithLockPath configures the path for the lockfile 15 func WithLockPath(lockpath string) Option { 16 return func(s *SingleInstance) { 17 s.path = lockpath 18 } 19 } 20 21 var ( 22 // ErrAlreadyRunning another instance of is already running 23 ErrAlreadyRunning = errors.New("another instance is already running") 24 ) 25 26 // SingleInstance represents the name and the open file descriptor 27 type SingleInstance struct { 28 name string 29 path string 30 file *os.File 31 } 32 33 // New creates a SingleInstance instance where name is the basename of the lock file (<name>.lock) 34 // if no path is given (WithLockPath option) the lock will be created in an operating specific path as <name>.lock 35 // panics if namr is empty 36 func New(name string, opts ...Option) *SingleInstance { 37 if name == "" { 38 panic("singleinstance: name cannot be empty") 39 } 40 41 s := &SingleInstance{ 42 name: name, 43 } 44 45 for _, o := range opts { 46 o(s) 47 } 48 49 if s.path == "" { 50 s.path = os.TempDir() 51 } 52 53 return s 54 } 55 56 // Lockfile returns the full path of the lock file 57 func (s *SingleInstance) Lockfile() string { 58 return filepath.Join(s.path, fmt.Sprintf("%s.lock", s.name)) 59 }