watchfs

package
v0.60.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 1, 2025 License: BSD-3-Clause Imports: 9 Imported by: 1

Documentation

Overview

Package watchfs implement naive file and directory watcher.

Index

Examples

Constants

View Source
const FileFlagDeleted = -1

FileFlagDeleted indicated that a file has been deleted. The flag is stored inside the os.FileInfo.Size.

Variables

This section is empty.

Functions

This section is empty.

Types

type DirWatcher

type DirWatcher struct {

	// C received the new, updated, and deleted files.
	C <-chan []os.FileInfo
	// contains filtered or unexported fields
}

DirWatcher scan the content of directory in watchfs.DirWatcherOptions.Root recursively for the files to be watched, using the watchfs.DirWatcherOptions.Includes field. A single file, watchfs.DirWatcherOptions.File, will be watched for changes that will trigger re-scanning the content of Root recursively.

The result of re-scanning is list of the Includes files (only files not new directory) that are changes, which will be send to channel C. On each os.FileInfo received from C, a deleted file have os.FileInfo.Size equal to FileFlagDeleted. The channel will send an empty slice if no changes.

The implementation of file changes in this code is naive, using loop and comparison of mode, modification time, and size; at least it should works on most operating system.

func WatchDir

func WatchDir(opts DirWatcherOptions) (dwatch *DirWatcher, err error)

WatchDir create and start scanning directory for changes.

Example
var (
	dirTemp string
	err     error
)
dirTemp, err = os.MkdirTemp(``, ``)
if err != nil {
	log.Fatal(err)
}

var (
	fileToWatch = filepath.Join(dirTemp, `.rescan`)
	opts        = watchfs.DirWatcherOptions{
		FileWatcherOptions: watchfs.FileWatcherOptions{
			File:     fileToWatch,
			Interval: 50 * time.Millisecond,
		},
		Root:     dirTemp,
		Includes: []string{`.*\.adoc$`},
		Excludes: []string{`exc$`, `.*\.html$`},
	}
	dwatch *watchfs.DirWatcher
)

dwatch, err = watchfs.WatchDir(opts)
if err != nil {
	log.Fatal(err)
}

var (
	fileAadoc = filepath.Join(opts.Root, `a.adoc`)
	fileBadoc = filepath.Join(opts.Root, `b.adoc`)
	fileAhtml = filepath.Join(opts.Root, `a.html`)
)

err = os.WriteFile(fileAadoc, nil, 0600)
if err != nil {
	log.Fatal(err)
}
err = os.WriteFile(fileAhtml, nil, 0600)
if err != nil {
	log.Fatal(err)
}
err = os.WriteFile(fileBadoc, nil, 0600)
if err != nil {
	log.Fatal(err)
}

// Write to the file that we watch for changes to trigger rescan.
err = os.WriteFile(fileToWatch, []byte(`x`), 0600)
if err != nil {
	log.Fatal(err)
}

var changes []os.FileInfo = <-dwatch.C
var names []string
for _, fi := range changes {
	// Since we use temporary directory, print only the base
	// name to make it works on all system.
	names = append(names, filepath.Base(fi.Name()))
}
sort.Strings(names)
fmt.Println(names)
Output:

[a.adoc b.adoc]

func (*DirWatcher) Files

func (dwatch *DirWatcher) Files() (files map[string]os.FileInfo)

Files return all the files currently being watched, the one that filtered by watchfs.DirWatcherOptions.Includes, with its file information. This method is not safe when called when DirWatcher has been running.

func (*DirWatcher) ForceRescan

func (dwatch *DirWatcher) ForceRescan()

ForceRescan force to rescan for changes without waiting for watchfs.DirWatcherOptions.File to be updated.

func (*DirWatcher) Stop

func (dwatch *DirWatcher) Stop()

Stop watching the file and re-scanning the Root directory.

type DirWatcherOptions

type DirWatcherOptions struct {
	FileWatcherOptions

	// The root directory where files to be scanned.
	Root string

	// List of regex for files or directories to be excluded from
	// scanning.
	// The Excludes option will be processed before Includes.
	Excludes []string

	// List of regex for files or directories to be included from
	// scanning.
	Includes []string
	// contains filtered or unexported fields
}

DirWatcherOptions contains options to watch directory.

type FileWatcher

type FileWatcher struct {

	// C receive new file information.
	C <-chan os.FileInfo
	// contains filtered or unexported fields
}

FileWatcher watch a single file. It will send the os.FileInfo to the channel C when the file is created, updated; or nil if file has been deleted.

The FileWatcher may stop unexpectedly when the os.Stat return an error other than os.ErrNotExist. The last error can be inspected using FileWatcher.Err.

func WatchFile

func WatchFile(opts FileWatcherOptions) (fwatch *FileWatcher)

WatchFile watch the file watchfs.FileWatcherOptions.File for being created, updated, or deleted; on every watchfs.FileWatcherOptions.Interval.

Example
var (
	name = `file.txt`
	opts = watchfs.FileWatcherOptions{
		File:     filepath.Join(os.TempDir(), name),
		Interval: 50 * time.Millisecond,
	}
)

fwatch := watchfs.WatchFile(opts)

// On create ...
_, err := os.Create(opts.File)
if err != nil {
	log.Fatal(err)
}

var fi os.FileInfo = <-fwatch.C
fmt.Printf("file %q created\n", fi.Name())

// On update ...
err = os.WriteFile(opts.File, nil, 0600)
if err != nil {
	log.Fatal(err)
}
fi = <-fwatch.C
fmt.Printf("file %q updated\n", fi.Name())

// On delete ...
err = os.Remove(opts.File)
if err != nil {
	log.Fatal(err)
}

fi = <-fwatch.C
fmt.Printf("file deleted: %v\n", fi)

fwatch.Stop()
Output:

file "file.txt" created
file "file.txt" updated
file deleted: <nil>

func (*FileWatcher) Err

func (fwatch *FileWatcher) Err() error

Err return the last error that cause the watch stopped.

func (*FileWatcher) Stop

func (fwatch *FileWatcher) Stop()

Stop watching the file.

type FileWatcherOptions

type FileWatcherOptions struct {
	// Path to the file to be watched.
	File string

	// Interval to check for file changes.
	Interval time.Duration
}

FileWatcherOptions define the options to watch file.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL