### Install VFS Source: https://github.com/c2fo/vfs/blob/main/README.md Install the vfs library using go get. ```bash go get -u github.com/c2fo/vfs/v7 ``` -------------------------------- ### Install Dropbox Backend Source: https://github.com/c2fo/vfs/blob/main/contrib/backend/dropbox/README.md Install the Dropbox backend for VFS using go get. ```bash go get github.com/c2fo/vfs/contrib/backend/dropbox ``` -------------------------------- ### Example Usage of S3Watcher Source: https://github.com/c2fo/vfs/blob/main/contrib/vfsevents/watchers/s3events/README.md Demonstrates initializing and starting the S3Watcher with custom SQS client and event handlers. Ensure context, event, and error handlers are properly defined. ```go package main import ( "context" "log" "github.com/c2fo/vfs/contrib/vfsevents" "github.com/c2fo/vfs/contrib/vfsevents/watchers/s3events" ) func main() { // Initialize the S3Watcher watcher, err := s3events.NewS3Watcher( "https://sqs.us-east-1.amazonaws.com/123456789012/my-queue", s3events.WithSqsClient(customSqsClient), s3events.WithReceivedCount(10), ) if err != nil { log.Fatal(fmt.Errorf("error creating S3Watcher: %w", err)) } // Define the event handler handler := func(event vfsevents.Event) { log.Printf("Event: %v\n", event) } // Define the error handler errHandler := func(err error) { log.Printf("Error: %v\n", err) } // Start the watcher ctx := context.Background() err = watcher.Start(ctx, handler, errHandler) if err != nil { log.Fatal(fmt.Errorf("error starting watcher: %v\n", err)) } // Run the watcher for 2 minutes time.Sleep(2 * time.Minute) watcher.Stop() } ``` -------------------------------- ### Basic FSNotify Watcher Usage Source: https://github.com/c2fo/vfs/blob/main/contrib/vfsevents/watchers/fsnotify/README.md Demonstrates the fundamental setup for the FSNotify watcher, including creating a VFS location, initializing the watcher, defining event and error handlers, and starting the watch process. ```go package main import ( "context" "fmt" "log" "time" "github.com/c2fo/vfs/contrib/vfsevents" "github.com/c2fo/vfs/contrib/vfsevents/watchers/fsnotify" "github.com/c2fo/vfs/v7/vfssimple" ) func main() { // Create a VFS location for local filesystem location, err := vfssimple.NewLocation("file:///path/to/watch") if err != nil { log.Fatal(err) } // Create FSNotify watcher watcher, err := fsnotify.NewFSNotifyWatcher(location) if err != nil { log.Fatal(err) } // Define event handler eventHandler := func(event vfsevents.Event) { fmt.Printf("Event: %s on %s\n", event.Type.String(), event.URI) } // Define error handler errorHandler := func(err error) { log.Printf("FSNotify error: %v", err) } // Start watching ctx := context.Background() if err := watcher.Start(ctx, eventHandler, errorHandler); err != nil { log.Fatal(err) } // Stop watching when done defer watcher.Stop() // Keep the program running select {} } ``` -------------------------------- ### Install vfsevents Library Source: https://github.com/c2fo/vfs/blob/main/contrib/vfsevents/README.md Install the vfsevents library using go get. ```bash go get github.com/c2fo/vfs/contrib/vfsevents ``` -------------------------------- ### Install VFS Lockfile Source: https://github.com/c2fo/vfs/blob/main/contrib/lockfile/README.md Install the VFS lockfile package using go get. ```bash go get github.com/c2fo/vfs/contrib/lockfile ``` -------------------------------- ### Start Source: https://github.com/c2fo/vfs/blob/main/contrib/vfsevents/watchers/fsnotify/README.md Starts watching the filesystem location for changes. ```APIDOC ## Start ### Description Starts watching the filesystem location for changes. ### Parameters #### Path Parameters - **ctx** (context.Context) - Required - Context for the operation #### Query Parameters - **handler** (vfsevents.HandlerFunc) - Required - Function to handle filesystem events - **errHandler** (vfsevents.ErrorHandlerFunc) - Required - Function to handle errors - **opts** (vfsevents.StartOption) - Optional - Options for starting the watcher ### Response #### Success Response (200) - **error** (error) - Error if starting fails ``` -------------------------------- ### Create and Start GCS Watcher Source: https://github.com/c2fo/vfs/blob/main/contrib/vfsevents/watchers/gcsevents/README.md Demonstrates how to create a new GCS watcher instance and start listening for events. Ensure you have the necessary context and a callback function to handle incoming events. ```go import "github.com/c2fo/vfs/contrib/vfsevents/watchers/gcsevents" // Create watcher watcher, err := gcsevents.NewGCSWatcher("my-project", "my-subscription") if err != nil { log.Fatal(err) } // Start watching err = watcher.Start(ctx, func(event vfsevents.Event) error { fmt.Printf("Event: %s on %s\n", event.Type, event.Path) return nil }) ``` -------------------------------- ### Initialize Mem FileSystem using Backend Source: https://github.com/c2fo/vfs/blob/main/docs/mem.md Demonstrates how to get an instance of the in-memory file system using the VFS backend interface. Ensure the 'mem' scheme is registered. ```go import ( "github.com/c2fo/vfs/v7/backend" "github.com/c2fo/vfs/v7/backend/mem" ) func UseFs() error { fs := backend.Backend(mem.Scheme) ... } ``` -------------------------------- ### Install s3events Package Source: https://github.com/c2fo/vfs/blob/main/contrib/vfsevents/watchers/s3events/README.md Install the s3events package using the go get command. ```bash go get github.com/c2fo/vfs/contrib/vfsevents/watchers/s3events ``` -------------------------------- ### Quick Start: Create and Write to a Local File Source: https://github.com/c2fo/vfs/blob/main/README.md This snippet demonstrates creating a local file using a URI and writing content to it with io.Copy. Ensure the file is closed after operations. ```go package main import ( "fmt" "strings" "io" "log" "github.com/c2fo/vfs/v7" "github.com/c2fo/vfs/v7/vfssimple" ) func main() { // Create local OS file from a URI osFile, err := vfssimple.NewFile("file:///tmp/example.txt") if err != nil { log.Fatal(err) } defer osFile.Close() // Write to the file _, err = io.Copy(osFile, strings.NewReader("Hello from vfs!")) if err != nil { log.Fatal(err) } if err := osFile.Close(); err != nil { log.Fatal(err) } fmt.Println("File created and written:", osFile.URI()) } ``` -------------------------------- ### Initialize FTP FileSystem using Backend Source: https://github.com/c2fo/vfs/blob/main/docs/ftp.md Use this snippet to get an FTP FileSystem instance via the generic backend interface. Ensure the ftp package is imported. ```go import ( "github.com/c2fo/vfs/v7/backend" "github.com/c2fo/vfs/v7/backend/ftp" ) func UseFs() error { fs := backend.Backend(ftp.Scheme) ... } ``` -------------------------------- ### Basic VFSPoller Usage Source: https://github.com/c2fo/vfs/blob/main/contrib/vfsevents/watchers/vfspoller/README.md Demonstrates how to create a VFS location, initialize a vfspoller with custom options, define event and error handlers, and start watching for file events. ```go package main import ( "context" "log" "time" "github.com/c2fo/vfs/contrib/vfsevents" "github.com/c2fo/vfs/contrib/vfsevents/watchers/vfspoller" "github.com/c2fo/vfs/v7/vfssimple" ) func main() { // Create a VFS location location, err := vfssimple.NewLocation("file:///tmp/watch") if err != nil { log.Fatal(err) } // Create poller with options poller, err := vfspoller.NewPoller(location, vfspoller.WithInterval(30*time.Second), // Poll every 30 seconds vfspoller.WithMinAge(5*time.Second), // Ignore files newer than 5 seconds vfspoller.WithMaxFiles(5000), // Limit cache to 5000 files vfspoller.WithCleanupAge(24*time.Hour), // Clean up old entries after 24 hours ) if err != nil { log.Fatal(err) } // Define event handler eventHandler := func(event vfsevents.Event) { log.Printf("File %s: %s at %s", event.Type.String(), event.URI, time.Unix(event.Timestamp, 0).Format("2006-01-02 15:04:05")) } // Define error handler errorHandler := func(err error) { log.Printf("Poller error: %v", err) } // Start watching ctx := context.Background() if err := poller.Start(ctx, eventHandler, errorHandler); err != nil { log.Fatal(err) } // Stop watching when done defer poller.Stop() // Keep the program running select {} } ``` -------------------------------- ### Initialize OS Backend using Backend Interface Source: https://github.com/c2fo/vfs/blob/main/docs/os.md Use this method to get an instance of the OS file system backend through the VFS backend interface. Ensure the 'os' package is imported. ```go import ( "github.com/c2fo/vfs/v7/backend" "github.com/c2fo/vfs/v7/backend/os" ) func UseFs() error { fs := backend.Backend(os.Scheme) ... } ``` -------------------------------- ### Start FSNotify Watcher Source: https://github.com/c2fo/vfs/blob/main/contrib/vfsevents/watchers/fsnotify/README.md Starts watching the filesystem location for changes. Requires a context, a handler function for events, an error handler function, and optional start options. ```go func (w *FSNotifyWatcher) Start( ctx context.Context, handler vfsevents.HandlerFunc, errHandler vfsevents.ErrorHandlerFunc, opts ...vfsevents.StartOption) error ``` -------------------------------- ### S3 Event Metadata Example Source: https://github.com/c2fo/vfs/blob/main/contrib/vfsevents/watchers/s3events/README.md Provides an example of the metadata associated with each VFS event, including bucket name, object key, event name, and versioning details. ```go event.Metadata = map[string]string{ "bucketName": "my-bucket", // S3 bucket name "key": "path/to/file.txt", // Object key/path "eventName": "s3:ObjectCreated:Copy", // Original S3 event name "region": "us-east-1", // AWS region "eventTime": "2023-01-01T12:00:00.000Z", // Event timestamp "operation": "copy", // Operation type (put, post, copy, multipart, restore, delete) "versionId": "abc123...", // Object version ID (if versioning enabled) "isVersioned": "true", // Whether bucket has versioning enabled "eTag": "d41d8cd98f...", // Object ETag "sequencer": "0055AED6DCD90281E5", // Event sequence number "size": "1024", // Object size in bytes } ``` -------------------------------- ### Initialize Azure FileSystem using Backend Source: https://github.com/c2fo/vfs/blob/main/docs/azure.md Use this snippet to get an Azure FileSystem instance by referencing the backend scheme. This approach requires casting to azure.FileSystem to access specific methods. ```go import ( "github.com/c2fo/vfs/v7/backend" "github.com/c2fo/vfs/v7/backend/azure" ) func UseFs() error { fs := backend.Backend(azure.Scheme) // ... return nil } ``` -------------------------------- ### Example Unreleased CHANGELOG Entry Source: https://github.com/c2fo/vfs/blob/main/AGENTS.md Provides an example of an entry in the 'Unreleased' section of CHANGELOG.md, including added and fixed items. ```markdown ## [Unreleased] ### Added - New S3 backend option for custom endpoint configuration ### Fixed - Fixed file handle leak in os backend when operations fail - Corrected path separator handling on Windows ``` -------------------------------- ### vfsevents Start Options Source: https://github.com/c2fo/vfs/blob/main/contrib/vfsevents/README.md Configure the watcher's behavior during startup using functional options like event filtering, status callbacks, and retry configurations. ```go // Event filtering - only process events that match criteria vfsevents.WithEventFilter(func(e Event) bool { return e.Type == EventCreated && strings.HasSuffix(e.URI, ".txt") }) // Status callbacks - receive watcher status updates vfsevents.WithStatusCallback(func(status WatcherStatus) { log.Printf("Events processed: %d, Running: %v", status.EventsProcessed, status.Running) }) // Retry configuration - handle transient failures gracefully vfsevents.WithRetryConfig(vfsevents.DefaultRetryConfig()) vfsevents.WithMaxRetries(5) vfsevents.WithRetryBackoff(2*time.Second, 60*time.Second) // Custom retryable error patterns vfsevents.WithRetryableErrors([]string{"custom error pattern"}) ``` -------------------------------- ### Update Workflow File Example Source: https://github.com/c2fo/vfs/blob/main/AGENTS.md Shows the before and after state of a workflow file when updating an action's commit SHA. ```yaml # Before uses: actions/checkout@old-sha # v6.0.1 # After uses: actions/checkout@new-sha # v6.0.2 ``` -------------------------------- ### Backend Conformance Testing Source: https://github.com/c2fo/vfs/blob/main/docs/backend.md Provides examples for testing a custom backend implementation using the `backend/testsuite` package. Run tests with the `vfsintegration` tag. ```go //go:build vfsintegration package myexoticfilesystem import ( "os" "testing" "github.com/c2fo/vfs/v7/backend/testsuite" ) func TestConformance(t *testing.T) { fs := NewFileSystem(/* options */) location, _ := fs.NewLocation("", "/test-path/") testsuite.RunConformanceTests(t, location) } func TestIOConformance(t *testing.T) { fs := NewFileSystem(/* options */) location, _ := fs.NewLocation("", "/test-path/") testsuite.RunIOTests(t, location) } ``` -------------------------------- ### Configure FSNotify Watcher with Debouncing Source: https://github.com/c2fo/vfs/blob/main/contrib/vfsevents/watchers/fsnotify/README.md Example of setting up event debouncing for the FSNotify watcher with a specified time interval to consolidate events. ```go // Watch directory with 500ms debouncing watcher, err := fsnotify.NewFSNotifyWatcher(location, fsnotify.WithDebounce(500*time.Millisecond)) ``` -------------------------------- ### Get FTP Client Source: https://github.com/c2fo/vfs/blob/main/docs/ftp.md Retrieves the underlying FTP client, creating it if necessary. Authentication is resolved as described in the Overview. ```go func (fs *FileSystem) Client(ctx context.Context, authority utils.Authority) (types.Client, error) ``` -------------------------------- ### Initialize OS Backend Directly Source: https://github.com/c2fo/vfs/blob/main/docs/os.md Alternatively, you can directly instantiate the OS file system by importing the 'os' package with an alias. This approach bypasses the generic backend interface. ```go import _os "github.com/c2fo/vfs/v7/backend/os" func DoSomething() { fs := &_os.FileSystem{} ... } ``` -------------------------------- ### GitHub Actions SHA Pinning Example Source: https://github.com/c2fo/vfs/blob/main/AGENTS.md Illustrates the required format for pinning GitHub Actions to specific commit SHAs for enhanced security and reproducibility. ```yaml uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 ``` -------------------------------- ### Get Host and Port String from Authority Source: https://github.com/c2fo/vfs/blob/main/docs/utils.md Returns a concatenated string of the host and port from an `Authority` struct, separated by a colon. Example: "host.com:1234". ```go func (a Authority) HostPortStr() string ``` -------------------------------- ### Integrate Custom DeleteOption into Delete Operation Source: https://github.com/c2fo/vfs/blob/main/docs/options.md Show how to handle custom DeleteOption types within the file.Delete method. This example demonstrates checking for a 'MyTakeBackupDeleteOption' and performing a backup action. ```go func (f *File) Delete(opts ...options.DeleteOption) error { for _, o := range opts { switch o.(type) { case delete.AllVersions: allVersions = true case delete.MyTakeBackupDeleteOption: // do something to take backup default: } } ... ... } ``` -------------------------------- ### GCSEvents Watcher Example Source: https://github.com/c2fo/vfs/blob/main/contrib/vfsevents/README.md Configure a watcher for real-time GCS events using Pub/Sub subscriptions. Includes retry logic and extracts GCS-specific metadata like object name. ```go package main import ( "context" "fmt" "log" "github.com/c2fo/vfs/contrib/vfsevents" "github.com/c2fo/vfs/contrib/vfsevents/watchers/gcsevents" ) func main() { // Create GCS watcher watcher, err := gcsevents.NewGCSWatcher("my-project", "my-subscription") if err != nil { log.Fatal(err) } // Define handlers eventHandler := func(event vfsevents.Event) { fmt.Printf("GCS Event: %s on %s\n", event.Type.String(), event.URI) // Access GCS-specific metadata if objectName, exists := event.Metadata["objectName"]; exists { fmt.Printf("Object: %s\n", objectName) } } errorHandler := func(err error) { log.Printf("GCS watcher error: %v", err) } // Start watching with retry logic ctx := context.Background() err = watcher.Start(ctx, eventHandler, errorHandler, vfsevents.WithRetryConfig(vfsevents.DefaultRetryConfig()), ) if err != nil { log.Fatal(err) } defer watcher.Stop() select {} } ``` -------------------------------- ### Generate Mocks with Mockery v3 Source: https://github.com/c2fo/vfs/blob/main/AGENTS.md Use mockery v3 to generate mocks for interfaces, preferring the EXPECT() pattern for setup. Place generated mocks in a 'mocks/' subdirectory. ```go //go:generate mockery --name=InterfaceName --output=./mocks ``` ```go mockClient := mocks.NewMockSQSClient(t) mockClient.EXPECT().ReceiveMessage(mock.Anything, mock.MatchedBy(func(input *sqs.ReceiveMessageInput) bool { return *input.QueueUrl == queueURL })).Return(&sqs.ReceiveMessageOutput{Messages: messages}, nil) ``` -------------------------------- ### Initialize Mem FileSystem Directly Source: https://github.com/c2fo/vfs/blob/main/docs/mem.md Shows how to directly instantiate the in-memory file system using its constructor. This method bypasses the general backend registration. ```go import _mem "github.com/c2fo/vfs/v7/backend/mem" func DoSomething() { fs := _mem.NewFileSystem() ... ``` -------------------------------- ### Instantiate and Move Files with vfssimple Source: https://github.com/c2fo/vfs/blob/main/docs/vfssimple.md Demonstrates creating file system locations and files using URIs and moving a file from S3 to a local directory. ```go package main import ( "fmt" "github.com/c2fo/vfs/v7/vfssimple" ) func main() { myLocalDir, err := vfssimple.NewLocation("file:///tmp/") if err != nil { panic(err) } myS3File, err := vfssimple.NewFile("s3://mybucket/some/path/to/key.txt") if err != nil { panic(err) } localFile, err := myS3File.MoveToLocation(myLocalDir) if err != nil { panic(err) } fmt.Printf("moved %s to %s\n", myS3File, localFile) } ``` -------------------------------- ### S3Events Watcher Example Source: https://github.com/c2fo/vfs/blob/main/contrib/vfsevents/README.md Set up a watcher to receive real-time S3 events via SQS. Handles event types and extracts S3-specific metadata like bucket name and event type. ```go package main import ( "context" "fmt" "log" "github.com/c2fo/vfs/contrib/vfsevents" "github.com/c2fo/vfs/contrib/vfsevents/watchers/s3events" ) func main() { // Create S3 watcher watcher, err := s3events.NewS3Watcher("https://sqs.region.amazonaws.com/account/queue") if err != nil { log.Fatal(err) } // Define handlers eventHandler := func(event vfsevents.Event) { fmt.Printf("S3 Event: %s on %s\n", event.Type.String(), event.URI) // Access S3-specific metadata if bucketName, exists := event.Metadata["bucketName"]; exists { fmt.Printf("Bucket: %s\n", bucketName) } if eventType, exists := event.Metadata["eventType"]; exists { fmt.Printf("S3 Event Type: %s\n", eventType) } } errorHandler := func(err error) { log.Printf("S3 watcher error: %v", err) } // Start watching ctx := context.Background() err = watcher.Start(ctx, eventHandler, errorHandler) if err != nil { log.Fatal(err) } defer watcher.Stop() select {} } ``` -------------------------------- ### Using Registered Backend File Systems Source: https://github.com/c2fo/vfs/blob/main/docs/backend.md Demonstrates how to load and use different backend file systems (OS and S3) after they have been registered. Ensure all necessary backend packages are imported. ```go package main // import backend and each backend you intend to use import ( "github.com/c2fo/vfs/v7" "github.com/c2fo/vfs/v7/backend" "github.com/c2fo/vfs/v7/backend/os" "github.com/c2fo/vfs/v7/backend/s3" ) func main() { var err error var osfile, s3file vfs.File // THEN begin using the file systems osfile, err = backend.Backend(os.Scheme).NewFile("", "/path/to/file.txt") if err != nil { panic(err) } s3file, err = backend.Backend(s3.Scheme).NewFile("mybucket", "/some/file.txt") if err != nil { panic(err) } err = osfile.CopyTo(s3file) if err != nil { panic(err) } } ``` -------------------------------- ### Initialize GS FileSystem using Backend Source: https://github.com/c2fo/vfs/blob/main/docs/gs.md Use this method to initialize the GS FileSystem by referencing the backend scheme. Ensure the backend package is imported. ```go import ( "github.com/c2fo/vfs/v7/backend" "github.com/c2fo/vfs/v7/backend/gs" ) func UseFs() error { fs := backend.Backend(gs.Scheme) ... } ``` -------------------------------- ### Using a Custom Backend File System Source: https://github.com/c2fo/vfs/blob/main/docs/backend.md Demonstrates how to retrieve and use a custom backend file system after it has been registered. Ensure the custom backend package is imported. ```go package MyExoticFileSystem import( "github.com/c2fo/vfs/v7/backend" "github.com/acme/myexoticfilesystem" ) ... func useNewBackend() error { myExoticFs, err = backend.Backend(myexoticfilesystem.Scheme) ... } ``` -------------------------------- ### Start Poller Function Signature Source: https://github.com/c2fo/vfs/blob/main/contrib/vfsevents/watchers/vfspoller/README.md The signature for the Start method of the Poller, which begins polling for file changes and accepts event and error handlers. ```go func (s *Poller) Start(ctx context.Context, handler vfsevents.HandlerFunc, errHandler vfsevents.ErrorHandlerFunc) error ``` -------------------------------- ### Start S3Watcher Source: https://github.com/c2fo/vfs/blob/main/contrib/vfsevents/watchers/s3events/README.md Starts watching the SQS queue for S3 events. It triggers a handler on events and an error handler for any polling errors. Polling can be stopped by calling Stop. ```go func (w *S3Watcher) Start(ctx context.Context, handler vfsevents.HandlerFunc, errHandler func(error)) error ``` -------------------------------- ### Initialize FileSystem Source: https://github.com/c2fo/vfs/blob/main/docs/ftp.md Creates a new instance of the FileSystem struct. ```go func NewFileSystem() *FileSystem ``` -------------------------------- ### GitHub Actions CI/CD Integration Example Source: https://github.com/c2fo/vfs/blob/main/docs/conformance_tests.md Integrate VFS backend integration tests into a GitHub Actions workflow. Set necessary environment variables, including secrets and test paths, before running the tests. ```yaml # GitHub Actions example - name: Run Backend Integration Tests env: MY_BACKEND_TOKEN: ${{ secrets.MY_BACKEND_TOKEN }} MY_BACKEND_TEST_PATH: "/ci-test/" run: | go test -v -tags=vfsintegration ./path/to/backend ``` -------------------------------- ### Start Source: https://github.com/c2fo/vfs/blob/main/contrib/vfsevents/watchers/vfspoller/README.md Starts the VFS Poller to monitor a location for file changes. It accepts a context for cancellation, an event handler function to process detected events, and an error handler function to manage polling errors. Retry configurations and status callbacks can be provided as additional options. ```APIDOC ## Start ### Description Starts polling the location for file changes and triggers the handler on events. It also takes an error handler to handle any errors that occur during polling. The polling process can be stopped by calling `Stop`. ### Signature ```go func (s *Poller) Start(ctx context.Context, handler vfsevents.HandlerFunc, errHandler vfsevents.ErrorHandlerFunc) error ``` ### Options - `vfsevents.WithRetryConfig(retryConfig)`: Configures retry logic for transient errors. - `vfsevents.WithStatusCallback(func(status vfsevents.WatcherStatus))`: Registers a callback to monitor the poller's status, including retry attempts and last errors. ``` -------------------------------- ### Registering a Custom Backend File System Source: https://github.com/c2fo/vfs/blob/main/docs/backend.md Shows how to implement the required VFS interfaces and register a new custom backend file system using `backend.Register()`. This is typically done within an init() function. ```go package myexoticfilesystem import( ... "github.com/c2fo/vfs/v7" "github.com/c2fo/vfs/v7/backend" ) // IMPLEMENT vfs interfaces ... // register backend func init() { backend.Register("exfs", &MyExoticFileSystem{}) } ``` -------------------------------- ### Get FileSystem Name Source: https://github.com/c2fo/vfs/blob/main/docs/ftp.md Returns the display name for the FTP filesystem. ```go func (fs *FileSystem) Name() string ``` -------------------------------- ### Get FileSystem from Location Source: https://github.com/c2fo/vfs/blob/main/docs/ftp.md Returns the vfs.FileSystem interface associated with this FTP location. ```go func (l *Location) FileSystem() vfs.FileSystem ``` -------------------------------- ### Basic Lockfile Usage Source: https://github.com/c2fo/vfs/blob/main/contrib/lockfile/README.md Demonstrates creating a file and acquiring a lock for it. Ensure the lock is always released using defer. ```go import ( "github.com/c2fo/vfs/v7/vfssimple" "github.com/c2fo/vfs/contrib/lockfile" ) // Create a file using vfssimple f, err := vfssimple.NewFile("mem:///inbox/data.csv") if err != nil { log.Fatal(err) } // Create a lock for the file lock, err := lockfile.NewLock(f) if err != nil { log.Fatal(err) } // Try to acquire the lock if err := lock.Acquire(); err != nil { if errors.Is(err, lockfile.ErrLockAlreadyHeld) { log.Println("File is already being processed") return } log.Fatal(err) } deferr lock.Release() // Always release the lock when done // Safely process the file ``` -------------------------------- ### Get FileSystem Scheme Source: https://github.com/c2fo/vfs/blob/main/docs/ftp.md Returns the URI scheme for the FTP filesystem, which is 'ftp'. ```go func (fs *FileSystem) Scheme() string ``` -------------------------------- ### Import and Use S3 Backend Source: https://github.com/c2fo/vfs/blob/main/docs/s3.md Import the S3 backend and use it via the generic backend interface. This is the recommended way to initialize the S3 filesystem. ```go import ( "github.com/c2fo/vfs/v7/backend" "github.com/c2fo/vfs/v7/backend/s3" ) func UseFs() error { fs := backend.Backend(s3.Scheme) ... } ``` -------------------------------- ### Path Source: https://github.com/c2fo/vfs/blob/main/docs/gs.md Path returns the path of the file at the current location, starting with a leading '/'. ```APIDOC ## Path ### Description Returns the path of the file at the current location, beginning with a leading '/'. ### Method (*Location) Path ### Response #### Success Response - (string) - The path of the current location. ``` -------------------------------- ### Location.ListByPrefix Source: https://github.com/c2fo/vfs/blob/main/docs/os.md ListByPrefix returns a slice of file names in the top directory that start with the given prefix. ```APIDOC ## func (*Location) ListByPrefix ### Description ListByPrefix returns a slice of all files starting with "prefix" in the top directory of the location. ### Method N/A (Method on struct) ### Signature ```go func (l *Location) ListByPrefix(prefix string) ([]string, error) ``` ### Parameters #### Path Parameters - **prefix** (string) - Required - The prefix to filter file names by. ### Response #### Success Response - **files** ([]string) - A slice of file names matching the prefix. - **error** (error) - An error if the listing failed. ``` -------------------------------- ### Get Blob Properties Source: https://github.com/c2fo/vfs/blob/main/docs/azure.md Fetches the properties for the blob specified by the container URI and file path. ```APIDOC ## Get Blob Properties ### Description Fetches the properties for a specific blob identified by its container URI and file path. ### Method GET ### Endpoint `/{containerURI}/{filePath}` ### Parameters #### Path Parameters - **containerURI** (string) - Required - The URI of the container. - **filePath** (string) - Required - The path to the file within the container. ### Response #### Success Response (200) - **BlobProperties** (*BlobProperties) - An object containing the properties of the blob. - **error** (error) - nil if successful, otherwise an error object. ### Response Example ```json { "example": { "lastModified": "2023-10-27T10:00:00Z", "contentLength": 1024, "contentType": "text/plain" } } ``` ``` -------------------------------- ### Configure SFTP FileSystem with Client and Options Source: https://github.com/c2fo/vfs/blob/main/docs/sftp.md Demonstrates how to augment an SFTP FileSystem instance by providing a custom SSH client and specific connection options. This allows for fine-grained control over authentication and connection parameters. ```go func DoSomething() { // cast if fs was created using backend.Backend(). Not necessary if created directly from sftp.NewFileSystem(). fs := backend.Backend(sftp.Scheme) fs = fs.(*sftp.FileSystem) // to pass specific client sshClient, err := ssh.Dial("tcp", "myuser@server.com:22", &ssh.ClientConfig{ User: "someuser", Auth: []ssh.AuthMethod{ssh.Password("mypassword")}, HostKeyCallback: ssh.InsecureIgnoreHostKey, }) // handle error client, err := _sftp.NewClient(sshClient) // handle error fs = fs.WithClient(client) // to pass in client options. See Options for more info. Note that changes to Options will make nil any client. // This behavior ensures that changes to settings will get applied to a newly created client. fs = fs.WithOptions( sftp.Options{ KeyFilePath: "/home/Bob/.ssh/id_rsa", KeyPassphrase: "s3cr3t", KnownHostsCallback: ssh.InsecureIgnoreHostKey, }, ) location, err := fs.NewLocation("myuser@server.com:22", "/some/path/") // handle error file := location.NewFile("myfile.txt") // handle error _, err := file.Write([]bytes("some text") // handle error err := file.Close() // handle error } ``` -------------------------------- ### Get FTP Location Path Source: https://github.com/c2fo/vfs/blob/main/docs/ftp.md Returns the current path string that the FTP location references. ```go func (l *Location) Path() string ``` -------------------------------- ### Get Username from UserInfo Source: https://github.com/c2fo/vfs/blob/main/docs/utils.md Retrieves the username from a `UserInfo` struct. Returns an empty string if no username is set. ```go func (u UserInfo) Username() string ``` -------------------------------- ### FileSystem.WithOptions Source: https://github.com/c2fo/vfs/blob/main/docs/gs.md Sets options for the client and returns the FileSystem instance. This method is chainable. ```APIDOC ## WithOptions ### Description Sets options for the client and returns the FileSystem instance. This method is chainable. ### Method func ### Endpoint N/A ### Parameters - **opts** (vfs.Options) - Required - The options to set for the client. ### Request Example N/A ### Response #### Success Response - **FileSystem** (*FileSystem) - The FileSystem instance with the options set. #### Response Example N/A ``` -------------------------------- ### Get Password from UserInfo Source: https://github.com/c2fo/vfs/blob/main/docs/utils.md Retrieves the password from a `UserInfo` struct. Returns an empty string if no password is set. ```go func (u UserInfo) Password() string ``` -------------------------------- ### Initialize GS FileSystem Directly Source: https://github.com/c2fo/vfs/blob/main/docs/gs.md Directly instantiate the GS FileSystem using its constructor. This is an alternative to using the generic backend initialization. ```go import "github.com/c2fo/vfs/v7/backend/gs" func DoSomething() { fs := gs.NewFileSystem() ... } ``` -------------------------------- ### Get UserInfo from Authority Source: https://github.com/c2fo/vfs/blob/main/docs/utils.md Retrieves the `UserInfo` struct from an `Authority`. This contains the username and password components of the URI. ```go func (a Authority) UserInfo() UserInfo ``` -------------------------------- ### Configure FTP FileSystem with Options and Client Source: https://github.com/c2fo/vfs/blob/main/docs/ftp.md Configure the FTP FileSystem by casting to ftp.FileSystem and using WithClient and WithOptions. Options like Password, Protocol, and timeouts can be set. Note that changes to Options may invalidate an existing client. ```go import ( "os" "time" "github.com/c2fo/vfs/v7/backend" ftp "github.com/c2fo/vfs/v7/backend/ftp" _ftp "github.com/jlaffaye/ftp" ) func DoSomething() { // cast if fs was created using backend.Backend(). Not necessary if created directly from ftp.NewFileSystem(). fs := backend.Backend(ftp.Scheme) fs = fs.(*ftp.FileSystem) // to pass specific client implementing types.Client interface (in this case, _ftp github.com/jlaffaye/ftp) client, _ := _ftp.Dial("server.com:21") fs = fs.WithClient(client) // to pass in client options. See Options for more info. Note that changes to Options will make nil any client. // This behavior ensures that changes to settings will get applied to a newly created client. fs = fs.WithOptions( ftp.Options{ Password: "s3cr3t", DisableEPSV: true, Protocol: ftp.ProtocolFTPES, DialTimeout: 15 * time.Second, DebugWriter: os.Stdout, }, ) location, err := fs.NewLocation("myuser@server.com:21", "/some/path/") #handle error file, err := location.NewFile("myfile.txt") #handle error _, err = file.Write([]byte("some text")) #handle error err = file.Close() #handle error } ``` -------------------------------- ### Get Blob Properties Source: https://github.com/c2fo/vfs/blob/main/docs/azure.md Fetches the properties for a specific blob identified by its container URI and file path. ```go func (a *DefaultClient) Properties(containerURI, filePath string) (*BlobProperties, error) ``` -------------------------------- ### Initialize FTP FileSystem Directly Source: https://github.com/c2fo/vfs/blob/main/docs/ftp.md Instantiate the FTP FileSystem directly using ftp.NewFileSystem(). This is useful for direct access to FTP-specific methods. ```go import "github.com/c2fo/vfs/v7/backend/ftp" func DoSomething() { fs := ftp.NewFileSystem() location, err := fs.NewLocation("myuser@server.com:21", "/some/path/") if err != nil { #handle error } ... } ``` -------------------------------- ### EnsureLeadingSlash Source: https://github.com/c2fo/vfs/blob/main/docs/utils.md Ensures that a given directory path starts with a leading slash. If the path does not have a leading slash, it adds one. ```APIDOC ## func EnsureLeadingSlash ### Description EnsureLeadingSlash is like EnsureTrailingSlash except that it adds the leading slash if needed. ### Signature ```go func EnsureLeadingSlash(dir string) string ``` ``` -------------------------------- ### Augment Azure FileSystem with Options or Client Source: https://github.com/c2fo/vfs/blob/main/docs/azure.md Demonstrates how to augment an existing Azure FileSystem instance with specific options like account credentials or a custom client (e.g., a mock client). This is typically done after obtaining the FileSystem via backend.Backend() and casting it. ```go import ( "github.com/c2fo/vfs/v7/backend/azure" "path/to/mocks" ) func DoSomething() { // ... var fs vfs.FileSystem // Assuming fs is already initialized and possibly cast // Cast if fs was created using backend.Backend(). Not necessary if created directly from azure.NewFileSystem(). fs = fs.(azure.FileSystem) // To pass in client options fs = fs.WithOptions( azure.Options{ AccountName: "...", AccountKey: "..." }, ) // To pass a specific client, for instance a mock client client := &mocks.Client{} fs = fs.WithClient(client) } ``` -------------------------------- ### Get Location URI from VFS Location Source: https://github.com/c2fo/vfs/blob/main/docs/utils.md Converts a VFS Location object into its corresponding URI string representation. ```go func GetLocationURI(l vfs.Location) string GetLocationURI returns a Location URI ``` -------------------------------- ### Registering a Community Backend Source: https://github.com/c2fo/vfs/blob/main/contrib/backend/README.md Register your backend's file system implementation using the `backend.Register` function within the `init()` function of your package. ```go func init() { backend.Register(Scheme, NewFileSystem()) } ``` -------------------------------- ### Get File URI from VFS File Source: https://github.com/c2fo/vfs/blob/main/docs/utils.md Converts a VFS File object into its corresponding URI string representation. ```go func GetFileURI(f vfs.File) string GetFileURI returns a File URI ``` -------------------------------- ### SFTP FileSystem Initialization Source: https://github.com/c2fo/vfs/blob/main/docs/sftp.md Provides a constructor for creating a new SFTP FileSystem instance and accessing its underlying SFTP client. ```APIDOC ## FileSystem Operations ### Description The `FileSystem` type implements the `vfs.FileSystem` interface for SFTP and provides methods to initialize and access its client. ### Methods - **NewFileSystem() *FileSystem** Initializes and returns a new `FileSystem` struct. - **Client(authority utils.Authority) (Client, error)** Returns the underlying SFTP client, creating it if necessary. Authentication is resolved based on the provided authority. - **Name() string** Returns the name of the file system, which is "Secure File Transfer Protocol". ``` -------------------------------- ### Get Lock Metadata Source: https://github.com/c2fo/vfs/blob/main/contrib/lockfile/README.md Retrieve metadata associated with an acquired lock, including hostname, PID, and creation timestamp. ```go // Get lock metadata meta, err := lock.Metadata() if err == nil { log.Printf("Lock held by %s (PID: %d) since %v", meta.Hostname, meta.PID, meta.CreatedAt) } ``` -------------------------------- ### Directly Initialize S3 FileSystem Source: https://github.com/c2fo/vfs/blob/main/docs/s3.md Initialize the S3 FileSystem directly using its constructor. This bypasses the generic backend interface. ```go import "github.com/c2fo/vfs/v7/backend/s3" func DoSomething() { fs := s3.NewFileSystem() ... } ``` -------------------------------- ### Get FTP Location URI String Source: https://github.com/c2fo/vfs/blob/main/docs/ftp.md Implements fmt.Stringer, returning the location's URI as its default string representation. ```go func (l *Location) String() string ``` -------------------------------- ### Touch Operation for New Files Source: https://github.com/c2fo/vfs/blob/main/contrib/backend/dropbox/README.md Demonstrates the efficient creation of a new, empty file using the Touch operation. This is contrasted with the expensive touch operation on existing files. ```go file, _ := fs.NewFile("", "/file.txt") // Efficient for new files file.Touch() // Creates empty file ``` -------------------------------- ### Validate Absolute File Path Source: https://github.com/c2fo/vfs/blob/main/docs/utils.md Ensures that a file path is absolute, meaning it starts with a leading slash but does not end with a trailing slash. ```go func ValidateAbsoluteFilePath(name string) error ValidateAbsoluteFilePath ensures that a file path has a leading slash but not a trailing slash ``` -------------------------------- ### VFSPoller with Retry Configuration Source: https://github.com/c2fo/vfs/blob/main/contrib/vfsevents/watchers/vfspoller/README.md Shows how to enable and configure retry logic for transient errors during directory listing operations when starting the poller. ```go // Start with retry configuration err := poller.Start(ctx, eventHandler, errorHandler, vfsevents.WithRetryConfig(vfsevents.RetryConfig{ Enabled: true, MaxRetries: 3, // Maximum retry attempts InitialBackoff: 1 * time.Second, // Initial backoff delay MaxBackoff: 30 * time.Second, // Maximum backoff delay BackoffFactor: 2.0, // Exponential backoff multiplier RetryableErrors: []string{ // Custom retryable error patterns "timeout", "connection", "SlowDown", "ServiceUnavailable", }, }), ) ``` -------------------------------- ### Set Up and Run Integration Tests Source: https://github.com/c2fo/vfs/blob/main/contrib/backend/dropbox/README.md Configure and execute integration tests for the Dropbox backend. This requires setting environment variables for authentication and test locations. ```bash # Set your access token export VFS_DROPBOX_ACCESS_TOKEN="your-token-here" # Set test location export VFS_INTEGRATION_LOCATIONS="dbx:///vfs-test/" # Run integration tests go test -v ./backend/testsuite/ -run TestIOSuite ``` -------------------------------- ### FileSystem.NewFileSystem Source: https://github.com/c2fo/vfs/blob/main/docs/gs.md Initializes a new FileSystem for Google Cloud Storage. It can accept a Google Cloud Storage client and returns a FileSystem instance. ```APIDOC ## NewFileSystem ### Description Initializes a new FileSystem for Google Cloud Storage. It can accept a Google Cloud Storage client and returns a FileSystem instance. ### Method func ### Endpoint N/A ### Parameters N/A ### Request Example N/A ### Response #### Success Response - **FileSystem** (*FileSystem) - The initialized FileSystem instance. #### Response Example N/A ``` -------------------------------- ### Configure FSNotify Watcher for Recursive Watching Source: https://github.com/c2fo/vfs/blob/main/contrib/vfsevents/watchers/fsnotify/README.md Example of enabling recursive watching for the FSNotify watcher, which will monitor the specified directory and all its subdirectories. ```go // Watch directory and all subdirectories watcher, err := fsnotify.NewFSNotifyWatcher(location, fsnotify.WithRecursive(true)) ``` -------------------------------- ### Basic Dropbox VFS Usage Source: https://github.com/c2fo/vfs/blob/main/contrib/backend/dropbox/README.md Demonstrates basic VFS operations with the Dropbox backend, including creating a file and writing content. Ensure the backend is registered via its import path. ```go package main import ( "fmt" "io" "os" "github.com/c2fo/vfs/v7/backend" _ "github.com/c2fo/vfs/contrib/backend/dropbox" ) func main() { // Get Dropbox filesystem from backend registry fs := backend.Backend(dropbox.Scheme) // Create a file file, err := fs.NewFile("", "/path/to/file.txt") if err != nil { panic(err) } // Write content _, err = file.Write([]byte("Hello, Dropbox!")) if err != nil { panic(err) } // Close to commit the write err = file.Close() if err != nil { panic(err) } } ``` -------------------------------- ### Initialize Dropbox VFS with Different Token Sources Source: https://github.com/c2fo/vfs/blob/main/contrib/backend/dropbox/README.md Demonstrates initializing the VFS Dropbox backend with various types of access tokens: manually generated for testing, obtained via OAuth2, or refreshed using a refresh token. The backend treats all valid access tokens identically. ```go // These all work the same way: // 1. Manual token (testing) fs := dropbox.NewFileSystem( dropbox.WithAccessToken("manually-generated-token"), ) // 2. OAuth2 token (production) fs := dropbox.NewFileSystem( dropbox.WithAccessToken(oauth2Token.AccessToken), ) // 3. Refreshed token (production) fs := dropbox.NewFileSystem( dropbox.WithAccessToken(refreshedToken.AccessToken), ) ``` -------------------------------- ### Example CHANGELOG Breaking Change Source: https://github.com/c2fo/vfs/blob/main/AGENTS.md Demonstrates the required format for a breaking change in the CHANGELOG.md file, including the 'BREAKING CHANGE' keyword. ```markdown ### Changed - **BREAKING CHANGE**: Modified API behavior to return errors instead of panicking ``` -------------------------------- ### Azure FileSystem Usage Source: https://github.com/c2fo/vfs/blob/main/docs/azure.md Demonstrates how to obtain and use the Azure FileSystem, either through the backend package or directly. ```APIDOC ## Azure FileSystem Usage This section shows how to initialize and use the Azure FileSystem. ### Using the Backend Package ```go import ( "github.com/c2fo/vfs/v7/backend" "github.com/c2fo/vfs/v7/backend/azure" ) func UseFs() error { fs := backend.Backend(azure.Scheme) // ... use fs ... return nil } ``` ### Direct Initialization ```go import "github.com/c2fo/vfs/v7/backend/azure" func DoSomething() { fs := azure.NewFileSystem() // ... use fs ... } ``` ### Augmenting FileSystem with Options Azure FileSystem can be augmented with specific options or clients. If `fs` was created using `backend.Backend()`, it needs to be cast to `azure.FileSystem`. ```go import ( "github.com/c2fo/vfs/v7/backend/azure" // Assuming mocks are available for testing // "path/to/mocks" ) func AugmentFs() { // Assume fs is initialized, e.g., via backend.Backend() or azure.NewFileSystem() var fs interface{} // Placeholder for initialized FileSystem // Cast if fs was created using backend.Backend() // fs = fs.(azure.FileSystem) // To pass in client options fs = fs.(azure.FileSystem).WithOptions( azure.Options{ AccountName: "...", AccountKey: "...", }, ) // To pass a specific client, for instance, a mock client // client := &mocks.Client{} // fs = fs.WithClient(client) } ``` ``` -------------------------------- ### Get Host from Authority Source: https://github.com/c2fo/vfs/blob/main/docs/utils.md Retrieves the host portion of an `Authority` struct. This method is useful for accessing just the domain name or IP address. ```go func (a Authority) Host() string ``` -------------------------------- ### Get FTP Retry Strategy Source: https://github.com/c2fo/vfs/blob/main/docs/ftp.md Returns the default no-op retrier. The FTP client has its own retryer, which can be overridden using FileSystem Options. ```go func (fs *FileSystem) Retry() vfs.Retry ``` -------------------------------- ### Set FileSystem Options Source: https://github.com/c2fo/vfs/blob/main/docs/ftp.md Allows setting options for the FTP filesystem, such as client configuration. This method is chainable. ```go func (fs *FileSystem) WithOptions(opts vfs.Options) *FileSystem ``` -------------------------------- ### Initialize Dropbox File System with Access Token Source: https://github.com/c2fo/vfs/blob/main/contrib/backend/dropbox/README.md Initializes a new Dropbox file system instance using an access token. This is a prerequisite for performing file operations. ```go fs := dropbox.NewFileSystem( dropbox.WithAccessToken(token), ) ``` -------------------------------- ### Get String Representation of Authority Source: https://github.com/c2fo/vfs/blob/main/docs/utils.md Returns a string representation of the `Authority`. It intentionally omits the password component as per RFC3986 section 3.2.1. ```go func (a Authority) String() string ``` -------------------------------- ### SFTP FileSystem Client Method Source: https://github.com/c2fo/vfs/blob/main/docs/sftp.md Returns the underlying SFTP client, creating it if necessary. Handles authentication resolution. ```go func (fs *FileSystem) Client(authority utils.Authority) (Client, error) ``` -------------------------------- ### Import SFTP Backend using Backend() Source: https://github.com/c2fo/vfs/blob/main/docs/sftp.md Import the SFTP backend using the generic backend function. This is useful when you want to abstract the specific backend implementation. ```go import ( "github.com/c2fo/vfs/v7/backend" "github.com/c2fo/vfs/v7/backend/sftp" ) func UseFs() error { fs := backend.Backend(sftp.Scheme) ... } ```