Update dependencies

This commit is contained in:
bluepython508
2024-11-01 17:33:34 +00:00
parent 033ac0b400
commit 5cdfab398d
3596 changed files with 1033483 additions and 259 deletions

8
vendor/github.com/illarion/gonotify/v2/.gitignore generated vendored Normal file
View File

@@ -0,0 +1,8 @@
*.so
*.dylib
# Test binary, build with `go test -c`
*.test
# Output of the go coverage tool, specifically when used with LiteIDE
*.out

21
vendor/github.com/illarion/gonotify/v2/LICENSE generated vendored Normal file
View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2018-2023 Ilarion Kovalchuk
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

67
vendor/github.com/illarion/gonotify/v2/README.md generated vendored Normal file
View File

@@ -0,0 +1,67 @@
## Gonotify
Simple Golang inotify wrapper.
[![GoDoc](https://godoc.org/github.com/illarion/gonotify/v2?status.svg)](https://godoc.org/github.com/illarion/gonotify/v2)
### Provides following primitives:
* Low level
* `Inotify` - wrapper around [inotify(7)](http://man7.org/linux/man-pages/man7/inotify.7.html)
* `InotifyEvent` - generated file/folder event. Contains `Name` (full path), watch descriptior and `Mask` that describes the event.
* Higher level
* `FileWatcher` - higher level utility, helps to watch the list of files for changes, creation or removal
* `DirWatcher` - higher level utility, recursively watches given root folder for added, removed or changed files.
* `FileEvent` - embeds `InotifyEvent` and keeps additional field `Eof` to notify user that there will be no more events.
Use `FileWatcher` and `DirWatcher` as an example and build your own utility classes.
### Usage
```go
package main
import (
"fmt"
"github.com/illarion/gonotify/v2"
"time"
"context"
)
func main() {
ctx, cancel := context.WithCancel(context.Background())
watcher, err := gonotify.NewDirWatcher(ctx, gonotify.IN_CREATE|gonotify.IN_CLOSE, "/tmp")
if err != nil {
panic(err)
}
for {
select {
case event := <-watcher.C:
fmt.Printf("Event: %s\n", event)
if event.Mask&gonotify.IN_CREATE != 0 {
fmt.Printf("File created: %s\n", event.Name)
}
if event.Mask&gonotify.IN_CLOSE != 0 {
fmt.Printf("File closed: %s\n", event.Name)
}
case <-time.After(5 * time.Second):
fmt.Println("Timeout")
cancel()
return
}
}
}
```
## License
MIT. See LICENSE file for more details.

156
vendor/github.com/illarion/gonotify/v2/dirwatcher.go generated vendored Normal file
View File

@@ -0,0 +1,156 @@
package gonotify
import (
"context"
"os"
"path/filepath"
)
// DirWatcher recursively watches the given root folder, waiting for file events.
// Events can be masked by providing fileMask. DirWatcher does not generate events for
// folders or subfolders.
type DirWatcher struct {
C chan FileEvent
}
// NewDirWatcher creates DirWatcher recursively waiting for events in the given root folder and
// emitting FileEvents in channel C, that correspond to fileMask. Folder events are ignored (having IN_ISDIR set to 1)
func NewDirWatcher(ctx context.Context, fileMask uint32, root string) (*DirWatcher, error) {
dw := &DirWatcher{
C: make(chan FileEvent),
}
ctx, cancel := context.WithCancel(ctx)
i, err := NewInotify(ctx)
if err != nil {
cancel()
return nil, err
}
queue := make([]FileEvent, 0, 100)
err = filepath.Walk(root, func(path string, f os.FileInfo, err error) error {
if err != nil {
return nil
}
if !f.IsDir() {
//fake event for existing files
queue = append(queue, FileEvent{
InotifyEvent: InotifyEvent{
Name: path,
Mask: IN_CREATE,
},
})
return nil
}
return i.AddWatch(path, IN_ALL_EVENTS)
})
if err != nil {
cancel()
return nil, err
}
events := make(chan FileEvent)
go func() {
for _, event := range queue {
events <- event
}
queue = nil
for {
raw, err := i.Read()
if err != nil {
close(events)
return
}
for _, event := range raw {
// Skip ignored events queued from removed watchers
if event.Mask&IN_IGNORED == IN_IGNORED {
continue
}
// Add watch for folders created in watched folders (recursion)
if event.Mask&(IN_CREATE|IN_ISDIR) == IN_CREATE|IN_ISDIR {
// After the watch for subfolder is added, it may be already late to detect files
// created there right after subfolder creation, so we should generate such events
// ourselves:
filepath.Walk(event.Name, func(path string, f os.FileInfo, err error) error {
if err != nil {
return nil
}
if !f.IsDir() {
// fake event, but there can be duplicates of this event provided by real watcher
events <- FileEvent{
InotifyEvent: InotifyEvent{
Name: path,
Mask: IN_CREATE,
},
}
}
return nil
})
// Wait for further files to be added
i.AddWatch(event.Name, IN_ALL_EVENTS)
continue
}
// Remove watch for deleted folders
if event.Mask&IN_DELETE_SELF == IN_DELETE_SELF {
i.RmWd(event.Wd)
continue
}
// Skip sub-folder events
if event.Mask&IN_ISDIR == IN_ISDIR {
continue
}
events <- FileEvent{
InotifyEvent: event,
}
}
}
}()
go func() {
for {
select {
case <-ctx.Done():
return
case event, ok := <-events:
if !ok {
dw.C <- FileEvent{
Eof: true,
}
cancel()
return
}
// Skip events not conforming with provided mask
if event.Mask&fileMask == 0 {
continue
}
dw.C <- event
}
}
}()
return dw, nil
}

138
vendor/github.com/illarion/gonotify/v2/event.go generated vendored Normal file
View File

@@ -0,0 +1,138 @@
//go:build linux
// +build linux
package gonotify
import (
"fmt"
"strings"
"syscall"
)
const (
IN_ACCESS = uint32(syscall.IN_ACCESS) // File was accessed
IN_ATTRIB = uint32(syscall.IN_ATTRIB) // Metadata changed
IN_CLOSE_WRITE = uint32(syscall.IN_CLOSE_WRITE) // File opened for writing was closed.
IN_CLOSE_NOWRITE = uint32(syscall.IN_CLOSE_NOWRITE) // File or directory not opened for writing was closed.
IN_CREATE = uint32(syscall.IN_CREATE) // File/directory created in watched directory
IN_DELETE = uint32(syscall.IN_DELETE) // File/directory deleted from watched directory.
IN_DELETE_SELF = uint32(syscall.IN_DELETE_SELF) // Watched file/directory was itself deleted.
IN_MODIFY = uint32(syscall.IN_MODIFY) // File was modified
IN_MOVE_SELF = uint32(syscall.IN_MOVE_SELF) // Watched file/directory was itself moved.
IN_MOVED_FROM = uint32(syscall.IN_MOVED_FROM) // Generated for the directory containing the old filename when a file is renamed.
IN_MOVED_TO = uint32(syscall.IN_MOVED_TO) // Generated for the directory containing the new filename when a file is renamed.
IN_OPEN = uint32(syscall.IN_OPEN) // File or directory was opened.
IN_ALL_EVENTS = uint32(syscall.IN_ALL_EVENTS) // bit mask of all of the above events.
IN_MOVE = uint32(syscall.IN_MOVE) // Equates to IN_MOVED_FROM | IN_MOVED_TO.
IN_CLOSE = uint32(syscall.IN_CLOSE) // Equates to IN_CLOSE_WRITE | IN_CLOSE_NOWRITE.
/* The following further bits can be specified in mask when calling Inotify.AddWatch() */
IN_DONT_FOLLOW = uint32(syscall.IN_DONT_FOLLOW) // Don't dereference pathname if it is a symbolic link.
IN_EXCL_UNLINK = uint32(syscall.IN_EXCL_UNLINK) // Don't generate events for children if they have been unlinked from the directory.
IN_MASK_ADD = uint32(syscall.IN_MASK_ADD) // Add (OR) the events in mask to the watch mask
IN_ONESHOT = uint32(syscall.IN_ONESHOT) // Monitor the filesystem object corresponding to pathname for one event, then remove from watch list.
IN_ONLYDIR = uint32(syscall.IN_ONLYDIR) // Watch pathname only if it is a directory.
/* The following bits may be set in the mask field returned by Inotify.Read() */
IN_IGNORED = uint32(syscall.IN_IGNORED) // Watch was removed explicitly or automatically
IN_ISDIR = uint32(syscall.IN_ISDIR) // Subject of this event is a directory.
IN_Q_OVERFLOW = uint32(syscall.IN_Q_OVERFLOW) // Event queue overflowed (wd is -1 for this event).
IN_UNMOUNT = uint32(syscall.IN_UNMOUNT) // Filesystem containing watched object was unmounted.
)
var in_mapping = map[uint32]string{
IN_ACCESS: "IN_ACCESS",
IN_ATTRIB: "IN_ATTRIB",
IN_CLOSE_WRITE: "IN_CLOSE_WRITE",
IN_CLOSE_NOWRITE: "IN_CLOSE_NOWRITE",
IN_CREATE: "IN_CREATE",
IN_DELETE: "IN_DELETE",
IN_DELETE_SELF: "IN_DELETE_SELF",
IN_MODIFY: "IN_MODIFY",
IN_MOVE_SELF: "IN_MOVE_SELF",
IN_MOVED_FROM: "IN_MOVED_FROM",
IN_MOVED_TO: "IN_MOVED_TO",
IN_OPEN: "IN_OPEN",
IN_IGNORED: "IN_IGNORED",
IN_ISDIR: "IN_ISDIR",
IN_Q_OVERFLOW: "IN_Q_OVERFLOW",
IN_UNMOUNT: "IN_UNMOUNT",
}
func InMaskToString(in_mask uint32) string {
sb := &strings.Builder{}
divide := false
for mask, str := range in_mapping {
if in_mask&mask == mask {
if divide {
sb.WriteString("|")
}
sb.WriteString(str)
divide = true
}
}
return sb.String()
}
// InotifyEvent is the go representation of inotify_event found in sys/inotify.h
type InotifyEvent struct {
// Watch descriptor
Wd uint32
// File or directory name
Name string
// Contains bits that describe the event that occurred
Mask uint32
// Usually 0, but if events (like IN_MOVED_FROM and IN_MOVED_TO) are linked then they will have equal cookie
Cookie uint32
}
func (i InotifyEvent) GoString() string {
return fmt.Sprintf("gonotify.InotifyEvent{Wd=%#v, Name=%s, Cookie=%#v, Mask=%#v=%s}", i.Wd, i.Name, i.Cookie, i.Mask, InMaskToString(i.Mask))
}
func (i InotifyEvent) String() string {
return fmt.Sprintf("{Wd=%d, Name=%s, Cookie=%d, Mask=%s}", i.Wd, i.Name, i.Cookie, InMaskToString(i.Mask))
}
// IsAny returns true if any of the in_mask is set in the event
func (i InotifyEvent) IsAny(in_mask ...uint32) bool {
for _, mask := range in_mask {
if i.Mask&mask == mask {
return true
}
}
return false
}
// IsAll returns true if all the in_masks is set in the event
func (i InotifyEvent) IsAll(in_mask ...uint32) bool {
for _, mask := range in_mask {
if i.Mask&mask != mask {
return false
}
}
return true
}
func (i InotifyEvent) Is(in_mask uint32) bool {
return i.Mask&in_mask == in_mask
}
// FileEvent is the wrapper around InotifyEvent with additional Eof marker. Reading from
// FileEvents from DirWatcher.C or FileWatcher.C may end with Eof when underlying inotify is closed
type FileEvent struct {
InotifyEvent
Eof bool
}
func (f FileEvent) GoString() string {
return fmt.Sprintf("gonotify.FileEvent{InotifyEvent=%#v, Eof=%#v}", f.InotifyEvent, f.Eof)
}
func (f FileEvent) String() string {
return fmt.Sprintf("{InotifyEvent=%s, Eof=%v}", f.InotifyEvent, f.Eof)
}

89
vendor/github.com/illarion/gonotify/v2/filewatcher.go generated vendored Normal file
View File

@@ -0,0 +1,89 @@
package gonotify
import (
"context"
"path/filepath"
)
// FileWatcher waits for events generated by filesystem for a specific list of file paths, including
// IN_CREATE for not yet existing files and IN_DELETE for removed.
type FileWatcher struct {
C chan FileEvent
}
// NewFileWatcher creates FileWatcher with provided inotify mask and list of files to wait events for.
func NewFileWatcher(ctx context.Context, mask uint32, files ...string) (*FileWatcher, error) {
f := &FileWatcher{
C: make(chan FileEvent),
}
ctx, cancel := context.WithCancel(ctx)
inotify, err := NewInotify(ctx)
if err != nil {
cancel()
return nil, err
}
expectedPaths := make(map[string]bool)
for _, file := range files {
err := inotify.AddWatch(filepath.Dir(file), mask)
if err != nil {
cancel()
return nil, err
}
expectedPaths[file] = true
}
events := make(chan FileEvent)
go func() {
defer cancel()
for {
raw, err := inotify.Read()
if err != nil {
close(events)
return
}
for _, event := range raw {
select {
case <-ctx.Done():
return
case events <- FileEvent{
InotifyEvent: event,
}: //noop
}
}
}
}()
go func() {
defer cancel()
for {
select {
case <-ctx.Done():
return
case event, ok := <-events:
if !ok {
f.C <- FileEvent{
Eof: true,
}
return
}
if !expectedPaths[event.Name] {
continue
}
f.C <- event
}
}
}()
return f, nil
}

290
vendor/github.com/illarion/gonotify/v2/inotify.go generated vendored Normal file
View File

@@ -0,0 +1,290 @@
//go:build linux
// +build linux
package gonotify
import (
"context"
"errors"
"fmt"
"path/filepath"
"strings"
"syscall"
"time"
"unsafe"
)
// max number of events to read at once
const maxEvents = 1024
var TimeoutError = errors.New("Inotify timeout")
type getWatchRequest struct {
pathName string
result chan uint32
}
type getPathRequest struct {
wd uint32
result chan string
}
type addWatchRequest struct {
pathName string
wd uint32
}
// Inotify is the low level wrapper around inotify_init(), inotify_add_watch() and inotify_rm_watch()
type Inotify struct {
// ctx is the context of inotify instance
ctx context.Context
// fd is the file descriptor of inotify instance
fd int
// getWatchByPathIn is the channel for getting watch descriptor by path
getWatchByPathIn chan getWatchRequest
// getPathByWatchIn is the channel for getting path by watch descriptor
getPathByWatchIn chan getPathRequest
// addWatchIn is the channel for adding watch
addWatchIn chan addWatchRequest
// rmByWdIn is the channel for removing watch by watch descriptor
rmByWdIn chan uint32
// rmByPathIn is the channel for removing watch by path
rmByPathIn chan string
}
// NewInotify creates new inotify instance
func NewInotify(ctx context.Context) (*Inotify, error) {
fd, err := syscall.InotifyInit1(syscall.IN_CLOEXEC | syscall.IN_NONBLOCK)
if err != nil {
return nil, err
}
inotify := &Inotify{
ctx: ctx,
fd: fd,
getPathByWatchIn: make(chan getPathRequest),
getWatchByPathIn: make(chan getWatchRequest),
addWatchIn: make(chan addWatchRequest),
rmByWdIn: make(chan uint32),
rmByPathIn: make(chan string),
}
go func() {
watches := make(map[string]uint32)
paths := make(map[uint32]string)
for {
select {
case <-ctx.Done():
for _, w := range watches {
_, err := syscall.InotifyRmWatch(fd, w)
if err != nil {
continue
}
}
syscall.Close(fd)
return
case req := <-inotify.addWatchIn:
watches[req.pathName] = req.wd
paths[req.wd] = req.pathName
case req := <-inotify.getWatchByPathIn:
wd, ok := watches[req.pathName]
if !ok {
close(req.result)
}
req.result <- wd
close(req.result)
case req := <-inotify.getPathByWatchIn:
pathName, ok := paths[req.wd]
if !ok {
close(req.result)
}
req.result <- pathName
close(req.result)
case wd := <-inotify.rmByWdIn:
pathName, ok := paths[wd]
if !ok {
continue
}
delete(watches, pathName)
delete(paths, wd)
case pathName := <-inotify.rmByPathIn:
wd, ok := watches[pathName]
if !ok {
continue
}
delete(watches, pathName)
delete(paths, wd)
}
}
}()
return inotify, nil
}
// AddWatch adds given path to list of watched files / folders
func (i *Inotify) AddWatch(pathName string, mask uint32) error {
w, err := syscall.InotifyAddWatch(i.fd, pathName, mask)
if err != nil {
return err
}
select {
case <-i.ctx.Done():
return i.ctx.Err()
case i.addWatchIn <- addWatchRequest{
pathName: pathName,
wd: uint32(w)}:
return nil
}
}
// RmWd removes watch by watch descriptor
func (i *Inotify) RmWd(wd uint32) error {
select {
case <-i.ctx.Done():
return i.ctx.Err()
case i.rmByWdIn <- wd:
return nil
}
}
// RmWatch removes watch by pathName
func (i *Inotify) RmWatch(pathName string) error {
select {
case <-i.ctx.Done():
return i.ctx.Err()
case i.rmByPathIn <- pathName:
return nil
}
}
// Read reads portion of InotifyEvents and may fail with an error. If no events are available, it will
// wait forever, until context is cancelled.
func (i *Inotify) Read() ([]InotifyEvent, error) {
for {
evts, err := i.ReadDeadline(time.Now().Add(time.Millisecond * 200))
if err != nil {
if err == TimeoutError {
continue
}
return evts, err
}
if len(evts) > 0 {
return evts, nil
}
}
}
// ReadDeadline waits for InotifyEvents until deadline is reached, or context is cancelled. If
// deadline is reached, TimeoutError is returned.
func (i *Inotify) ReadDeadline(deadline time.Time) ([]InotifyEvent, error) {
events := make([]InotifyEvent, 0, maxEvents)
buf := make([]byte, maxEvents*(syscall.SizeofInotifyEvent+syscall.NAME_MAX+1))
var n int
var err error
fdset := &syscall.FdSet{}
//main:
for {
if i.ctx.Err() != nil {
return events, i.ctx.Err()
}
now := time.Now()
if now.After(deadline) {
return events, TimeoutError
}
diff := deadline.Sub(now)
timeout := syscall.NsecToTimeval(diff.Nanoseconds())
fdset.Bits[0] = 1 << uint(i.fd)
_, err = syscall.Select(i.fd+1, fdset, nil, nil, &timeout)
if err != nil {
if err == syscall.EINTR {
continue
}
return events, err
}
if fdset.Bits[0]&(1<<uint(i.fd)) == 0 {
continue // No data to read, continue waiting
}
n, err = syscall.Read(i.fd, buf)
if err != nil {
if err == syscall.EAGAIN {
continue
}
return events, err
}
if n > 0 {
break
}
}
if n < syscall.SizeofInotifyEvent {
return events, fmt.Errorf("short inotify read, expected at least one SizeofInotifyEvent %d, got %d", syscall.SizeofInotifyEvent, n)
}
offset := 0
for offset+syscall.SizeofInotifyEvent <= n {
event := (*syscall.InotifyEvent)(unsafe.Pointer(&buf[offset]))
var name string
{
nameStart := offset + syscall.SizeofInotifyEvent
nameEnd := offset + syscall.SizeofInotifyEvent + int(event.Len)
if nameEnd > n {
return events, fmt.Errorf("corrupted inotify event length %d", event.Len)
}
name = strings.TrimRight(string(buf[nameStart:nameEnd]), "\x00")
offset = nameEnd
}
req := getPathRequest{
wd: uint32(event.Wd),
result: make(chan string),
}
select {
case <-i.ctx.Done():
return events, i.ctx.Err()
case i.getPathByWatchIn <- req:
select {
case <-i.ctx.Done():
return events, i.ctx.Err()
case watchName := <-req.result:
name = filepath.Join(watchName, name)
}
}
events = append(events, InotifyEvent{
Wd: uint32(event.Wd),
Name: name,
Mask: event.Mask,
Cookie: event.Cookie,
})
}
return events, nil
}