From 7b4377ad9d8a7205416df8d6217ef2b010f89481 Mon Sep 17 00:00:00 2001 From: Taras Madan Date: Wed, 22 Jan 2025 16:07:17 +0100 Subject: vendor: delete --- vendor/github.com/chigopher/pathlib/.gitignore | 1 - vendor/github.com/chigopher/pathlib/.golangci.yml | 28 - vendor/github.com/chigopher/pathlib/.mockery.yaml | 4 - vendor/github.com/chigopher/pathlib/LICENSE | 201 ------- vendor/github.com/chigopher/pathlib/Makefile | 23 - vendor/github.com/chigopher/pathlib/README.md | 171 ------ vendor/github.com/chigopher/pathlib/errors.go | 29 - vendor/github.com/chigopher/pathlib/file.go | 9 - vendor/github.com/chigopher/pathlib/path.go | 657 ---------------------- vendor/github.com/chigopher/pathlib/vars.go | 9 - vendor/github.com/chigopher/pathlib/walk.go | 405 ------------- 11 files changed, 1537 deletions(-) delete mode 100644 vendor/github.com/chigopher/pathlib/.gitignore delete mode 100644 vendor/github.com/chigopher/pathlib/.golangci.yml delete mode 100644 vendor/github.com/chigopher/pathlib/.mockery.yaml delete mode 100644 vendor/github.com/chigopher/pathlib/LICENSE delete mode 100644 vendor/github.com/chigopher/pathlib/Makefile delete mode 100644 vendor/github.com/chigopher/pathlib/README.md delete mode 100644 vendor/github.com/chigopher/pathlib/errors.go delete mode 100644 vendor/github.com/chigopher/pathlib/file.go delete mode 100644 vendor/github.com/chigopher/pathlib/path.go delete mode 100644 vendor/github.com/chigopher/pathlib/vars.go delete mode 100644 vendor/github.com/chigopher/pathlib/walk.go (limited to 'vendor/github.com/chigopher/pathlib') diff --git a/vendor/github.com/chigopher/pathlib/.gitignore b/vendor/github.com/chigopher/pathlib/.gitignore deleted file mode 100644 index 36946b0e0..000000000 --- a/vendor/github.com/chigopher/pathlib/.gitignore +++ /dev/null @@ -1 +0,0 @@ -coverage.txt \ No newline at end of file diff --git a/vendor/github.com/chigopher/pathlib/.golangci.yml b/vendor/github.com/chigopher/pathlib/.golangci.yml deleted file mode 100644 index d167eea50..000000000 --- a/vendor/github.com/chigopher/pathlib/.golangci.yml +++ /dev/null @@ -1,28 +0,0 @@ -linters: - # Disable all linters. - # Default: false - disable-all: true - # Enable specific linter - # https://golangci-lint.run/usage/linters/#enabled-by-default - enable: - - errcheck - - gosimple - - govet - - ineffassign - - staticcheck - - typecheck - - contextcheck - - durationcheck - - exportloopref - - gocheckcompilerdirectives - - gosec - - loggercheck - - nilerr - - prealloc - - predeclared - - reassign -linters-settings: - staticcheck: - checks: - - all - - '-SA1024' \ No newline at end of file diff --git a/vendor/github.com/chigopher/pathlib/.mockery.yaml b/vendor/github.com/chigopher/pathlib/.mockery.yaml deleted file mode 100644 index ed1e168d6..000000000 --- a/vendor/github.com/chigopher/pathlib/.mockery.yaml +++ /dev/null @@ -1,4 +0,0 @@ -quiet: False -all: True -inpackage: True -testonly: True diff --git a/vendor/github.com/chigopher/pathlib/LICENSE b/vendor/github.com/chigopher/pathlib/LICENSE deleted file mode 100644 index 261eeb9e9..000000000 --- a/vendor/github.com/chigopher/pathlib/LICENSE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/vendor/github.com/chigopher/pathlib/Makefile b/vendor/github.com/chigopher/pathlib/Makefile deleted file mode 100644 index 262cbaa02..000000000 --- a/vendor/github.com/chigopher/pathlib/Makefile +++ /dev/null @@ -1,23 +0,0 @@ -SHELL=bash - -.PHONY: all -all: fmt mocks test install docker - -.PHONY: fmt -fmt: - go fmt ./... - -.PHONY: test -test: - go test -v -coverprofile=coverage.txt ./... - -.PHONY: test.ci -test.ci: test fmt - -.PHONY: lint -lint: - go run github.com/golangci/golangci-lint/cmd/golangci-lint@v1.52.2 run - -.PHONY: clean -clean: - rm -rf mocks \ No newline at end of file diff --git a/vendor/github.com/chigopher/pathlib/README.md b/vendor/github.com/chigopher/pathlib/README.md deleted file mode 100644 index ce14be4c1..000000000 --- a/vendor/github.com/chigopher/pathlib/README.md +++ /dev/null @@ -1,171 +0,0 @@ -pathlib -======== - -[![Build Status](https://travis-ci.org/chigopher/pathlib.svg?branch=master)](https://travis-ci.org/chigopher/pathlib) [![go.dev reference](https://img.shields.io/badge/go.dev-reference-007d9c?logo=go&logoColor=white&style=flat-square)](https://pkg.go.dev/github.com/chigopher/pathlib) ![GitHub release (latest by date)](https://img.shields.io/github/v/release/chigopher/pathlib?style=flat-square) [![codecov](https://codecov.io/gh/chigopher/pathlib/branch/master/graph/badge.svg)](https://codecov.io/gh/chigopher/pathlib) ![GitHub go.mod Go version](https://img.shields.io/github/go-mod/go-version/chigopher/pathlib?style=flat-square) ![License](https://img.shields.io/github/license/chigopher/pathlib?style=flat-square) - -Inspired by Python's pathlib, made better by Go. - -`pathlib` is an "object-oriented" package for manipulating filesystem path objects. It takes many cues from [Python's pathlib](https://docs.python.org/3/library/pathlib.html), although it does not strictly adhere to its design philosophy. It provides a simple, intuitive, easy, and abstracted interface for dealing with many different types of filesystems. - -`pathlib` is currently in the beta stage of development. The API is not guaranteed to be solidified, however changes will be as minimal as possible. - -Table of Contents ------------------ - - -* [Examples](#examples) - * [OsFs](#osfs) - * [In\-memory FS](#in-memory-fs) -* [Design Philosophy](#design-philosophy) - * [filepath\.Path](#filepathpath) - * [filepath\.File](#filepathfile) -* [Frequently Asked Questions](#frequently-asked-questions) - * [Why pathlib and not filepath?](#why-pathlib-and-not-filepath) - * [Why not use afero directly?](#why-not-use-afero-directly) - * [Does this provide any benefit to my unit tests?](#does-this-provide-any-benefit-to-my-unit-tests) - * [What filesystems does this support?](#what-filesystems-does-this-support) - - - -Examples ---------- - -### OsFs - -Beacuse `pathlib` treats `afero` filesystems as first-class citizens, you can instantiate a `Path` object with the filesystem of your choosing. - -#### Code - -```go -package main - -import ( - "fmt" - "os" - - "github.com/chigopher/pathlib" - "github.com/spf13/afero" -) - -func main() { - // Create a path on your regular OS filesystem - path := pathlib.NewPathAfero("/home/ltclipp", afero.NewOsFs()) - - subdirs, err := path.ReadDir() - if err != nil { - fmt.Printf("%v\n", err) - os.Exit(1) - } - - for _, dir := range subdirs { - fmt.Println(dir.Name()) - } -} -``` - -#### Output - -```bash -[ltclipp@landon-virtualbox examples]$ go build . -[ltclipp@landon-virtualbox examples]$ ./examples | tail -Music -Pictures -Public -Templates -Videos -git -go -mockery_test -snap -software -``` - -### In-memory FS - -#### Code -```go -package main - -import ( - "fmt" - "os" - - "github.com/chigopher/pathlib" - "github.com/spf13/afero" -) - -func main() { - // Create a path using an in-memory filesystem - path := pathlib.NewPathAfero("/", afero.NewMemMapFs()) - hello := path.Join("hello_world.txt") - hello.WriteFile([]byte("hello world!"), 0o644) - - subpaths, err := path.ReadDir() - if err != nil { - fmt.Printf("%v\n", err) - os.Exit(1) - } - - for _, subpath := range subpaths { - fmt.Printf("Name: %s Mode: %o Size: %d\n", subpath.Name(), subpath.Mode(), subpath.Size()) - } - - bytes, _ := hello.ReadFile() - fmt.Println(string(bytes)) -} -``` - -#### Output - -```bash -[ltclipp@landon-virtualbox examples]$ go build -[ltclipp@landon-virtualbox examples]$ ./examples -Name: hello_world.txt Mode: 644 Size: 12 -hello world! -``` - -Design Philosophy ------------------- - -The design philosophy of this package is to be as thin of a layer as possible to existing community-standard packages, like `io`, `afero`, and `os`. Additional functionality is provided in consise and logical ways to extend the existing community APIs. - -### `filepath.Path` - -The API of `filepath.Path` can be grouped into a few main categories: - -1. `github.com/spf13/afero.Fs` wrappers: these are methods that have nearly identical signatures to `afero.Fs`, with the exception of the path string (which is stored in the `pathlib.Path` object itself. `afero.Fs` is an object that is meant to interact directly with the filesystem. -2. `github.com/spf13/afero.Afero` wrappers: these are methods that again have nearly identical signatures to `afero.Afero`. `afero.Afero` is a convenience object that provides higher-level behavior to the underlying `afero.Fs` object. -3. Filesystem-specific methods: these are methods that are implemented by some, but not all, of the afero filesystems. These methods may fail at runtime if the filesystem you provide does not implement the required interface. -4. [Python's Pathlib](https://docs.python.org/3/library/pathlib.html)-inspired methods: these are methods that are not implemented in the previous two steps, and that provide the power behind the object-oriented design. -5. `github.com/chigopher/pathlib`-specific methods: these are miscellaneous methods that are not covered by any of the previous categories. These methods are typically conveniences around methods in one of the previous categories. - -### `filepath.File` - -`filepath.File` is intended to be a thin wrapper around [`afero.File`](https://pkg.go.dev/github.com/spf13/afero?tab=doc#File). We avoid simply returning this interface on calls to `Open()` and `OpenFile()` (etc) because we want the ability to extend our API beyond what `afero` provides. So, we create our own `File` object which embeds `afero.File`, but might possibly contain further functionality. - -### Whoa whoa whoa, what is this afero nonsense? - -[`github.com/spf13/afero`](https://github.com/spf13/afero) is a package that provides an abstracted interface to the underlying filesystem API calls. `pathlib` uses this package for operating on the abstracted filesystem. This is powerful because it allows you to to use essentially any kind of filesystem that you want. Additionally, afero is a first-class-citizen in `pathlib` meaning that you can implement and explicitly provide your own afero object. - -The basic diagram looks like this: - -![Pathlib Diagram](https://github.com/chigopher/pathlib/blob/master/docs/pathlib-diagram.png) - -Frequently Asked Questions --------------------------- - -### Why `pathlib` and not [`filepath`](https://golang.org/pkg/path/filepath/)? - -[`filepath`](https://golang.org/pkg/path/filepath/) is a package that is tightly coupled to the OS filesystem APIs and also is not written in an object-oriented way. `pathlib` uses [`afero`](https://github.com/spf13/afero) under the hood for its abstracted filesystem interface, which allows you to represent a vast array of different filesystems (e.g. SFTP, HTTP, in-memory, and of course OS filesystems) using the same `Path` object. - -### Why not use `afero` directly? - -You certainly could, however `afero` does not represent a _filesystem object_ in an object-oriented way. It is only object-oriented with respect to the filesystem itself. `pathlib` is simply a thin layer on top of `afero` that provides the filesystem-object-orientation. - -### Does this provide any benefit to my unit tests? - -Most certainly! `pathlib` allows you to create [in-memory filesystems](#in-memory-fs), which have the nice property of being automatically garbage collected by Golang's GC when they go out of scope. You don't have to worry about defering any `Remove()` functions or setting up temporary dirs in `/tmp`. Just instantiate a `MemMapFs` and you're good to go! - -### What filesystems does this support? - -Currently only POSIX-style paths are supported. diff --git a/vendor/github.com/chigopher/pathlib/errors.go b/vendor/github.com/chigopher/pathlib/errors.go deleted file mode 100644 index 28b6b9a2a..000000000 --- a/vendor/github.com/chigopher/pathlib/errors.go +++ /dev/null @@ -1,29 +0,0 @@ -package pathlib - -import "fmt" - -var ( - // ErrDoesNotImplement indicates that the afero filesystem doesn't - // implement the required interface. - ErrDoesNotImplement = fmt.Errorf("doesn't implement required interface") - // ErrInfoIsNil indicates that a nil os.FileInfo object was provided - ErrInfoIsNil = fmt.Errorf("provided os.Info object was nil") - // ErrInvalidAlgorithm specifies that an unknown algorithm was given for Walk - ErrInvalidAlgorithm = fmt.Errorf("invalid algorithm specified") - // ErrLstatNotPossible specifies that the filesystem does not support lstat-ing - ErrLstatNotPossible = fmt.Errorf("lstat is not possible") - // ErrRelativeTo indicates that we could not make one path relative to another - ErrRelativeTo = fmt.Errorf("failed to make path relative to other") - errWalkControl = fmt.Errorf("walk control") - // ErrSkipSubtree indicates to the walk function that the current subtree of - // directories should be skipped. It's recommended to only use this error - // with the AlgorithmPreOrderDepthFirst algorithm, as many other walk algorithms - // will not respect this error due to the nature of the ordering in which the - // algorithms visit each node of the filesystem tree. - ErrWalkSkipSubtree = fmt.Errorf("skip subtree: %w", errWalkControl) - // ErrStopWalk indicates to the Walk function that the walk should be aborted. - // DEPRECATED: Use ErrWalkStop - ErrStopWalk = ErrWalkStop - // ErrWalkStop indicates to the Walk function that the walk should be aborted. - ErrWalkStop = fmt.Errorf("stop filesystem walk: %w", errWalkControl) -) diff --git a/vendor/github.com/chigopher/pathlib/file.go b/vendor/github.com/chigopher/pathlib/file.go deleted file mode 100644 index 82e43e1fd..000000000 --- a/vendor/github.com/chigopher/pathlib/file.go +++ /dev/null @@ -1,9 +0,0 @@ -package pathlib - -import "github.com/spf13/afero" - -// File represents a file in the filesystem. It inherits the afero.File interface -// but might also include additional functionality. -type File struct { - afero.File -} diff --git a/vendor/github.com/chigopher/pathlib/path.go b/vendor/github.com/chigopher/pathlib/path.go deleted file mode 100644 index 2f802e159..000000000 --- a/vendor/github.com/chigopher/pathlib/path.go +++ /dev/null @@ -1,657 +0,0 @@ -package pathlib - -import ( - "fmt" - "io" - "os" - "path/filepath" - "strings" - "time" - - "github.com/spf13/afero" -) - -// Path is an object that represents a path -type Path struct { - path string - fs afero.Fs - - // DefaultFileMode is the mode that is used when creating new files in functions - // that do not accept os.FileMode as a parameter. - DefaultFileMode os.FileMode - // DefaultDirMode is the mode that will be used when creating new directories - DefaultDirMode os.FileMode - // Sep is the seperator used in path calculations. By default this is set to - // os.PathSeparator. - Sep string -} - -type PathOpts func(p *Path) - -func PathWithAfero(fs afero.Fs) PathOpts { - return func(p *Path) { - p.fs = fs - } -} - -func PathWithSeperator(sep string) PathOpts { - return func(p *Path) { - p.Sep = sep - } -} - -// NewPath returns a new OS path -func NewPath(path string, opts ...PathOpts) *Path { - p := &Path{ - path: path, - fs: afero.NewOsFs(), - DefaultFileMode: DefaultFileMode, - DefaultDirMode: DefaultDirMode, - Sep: string(os.PathSeparator), - } - for _, opt := range opts { - opt(p) - } - return p -} - -// NewPathAfero returns a Path object with the given Afero object -// -// Deprecated: Use the PathWithAfero option in Newpath instead. -func NewPathAfero(path string, fs afero.Fs) *Path { - return NewPath(path, PathWithAfero(fs)) -} - -// Glob returns all of the path objects matched by the given pattern -// inside of the afero filesystem. -func Glob(fs afero.Fs, pattern string) ([]*Path, error) { - matches, err := afero.Glob(fs, pattern) - if err != nil { - return nil, fmt.Errorf("failed to glob: %w", err) - } - - pathMatches := []*Path{} - for _, match := range matches { - pathMatches = append(pathMatches, NewPathAfero(match, fs)) - } - return pathMatches, nil -} - -type namer interface { - Name() string -} - -func getFsName(fs afero.Fs) string { - if name, ok := fs.(namer); ok { - return name.Name() - } - return "" -} - -// Fs returns the internal afero.Fs object. -func (p *Path) Fs() afero.Fs { - return p.fs -} - -func (p *Path) doesNotImplementErr(interfaceName string) error { - return doesNotImplementErr(interfaceName, p.Fs()) -} - -func doesNotImplementErr(interfaceName string, fs afero.Fs) error { - return fmt.Errorf("%w: Path's afero filesystem %s does not implement %s", ErrDoesNotImplement, getFsName(fs), interfaceName) -} - -func (p *Path) lstatNotPossible() error { - return lstatNotPossible(p.Fs()) -} - -func lstatNotPossible(fs afero.Fs) error { - return fmt.Errorf("%w: Path's afero filesystem %s does not support lstat", ErrLstatNotPossible, getFsName(fs)) -} - -// ******************************* -// * afero.Fs wrappers * -// ******************************* - -// Create creates a file if possible, returning the file and an error, if any happens. -func (p *Path) Create() (File, error) { - file, err := p.Fs().Create(p.String()) - return File{file}, err -} - -// Mkdir makes the current dir. If the parents don't exist, an error -// is returned. -func (p *Path) Mkdir() error { - return p.Fs().Mkdir(p.String(), p.DefaultDirMode) -} - -// MkdirMode makes the current dir. If the parents don't exist, an error -// is returned. -func (p *Path) MkdirMode(perm os.FileMode) error { - return p.Fs().Mkdir(p.String(), perm) -} - -// MkdirAll makes all of the directories up to, and including, the given path. -func (p *Path) MkdirAll() error { - return p.Fs().MkdirAll(p.String(), p.DefaultDirMode) -} - -// MkdirAllMode makes all of the directories up to, and including, the given path. -func (p *Path) MkdirAllMode(perm os.FileMode) error { - return p.Fs().MkdirAll(p.String(), perm) -} - -// Open opens a file for read-only, returning it or an error, if any happens. -func (p *Path) Open() (*File, error) { - handle, err := p.Fs().Open(p.String()) - return &File{ - File: handle, - }, err -} - -// OpenFile opens a file using the given flags. -// See the list of flags at: https://golang.org/pkg/os/#pkg-constants -func (p *Path) OpenFile(flag int) (*File, error) { - handle, err := p.Fs().OpenFile(p.String(), flag, p.DefaultFileMode) - return &File{ - File: handle, - }, err -} - -// OpenFileMode opens a file using the given flags and the given mode. -// See the list of flags at: https://golang.org/pkg/os/#pkg-constants -func (p *Path) OpenFileMode(flag int, perm os.FileMode) (*File, error) { - handle, err := p.Fs().OpenFile(p.String(), flag, perm) - return &File{ - File: handle, - }, err -} - -// Remove removes a file, returning an error, if any -// happens. -func (p *Path) Remove() error { - return p.Fs().Remove(p.String()) -} - -// RemoveAll removes the given path and all of its children. -func (p *Path) RemoveAll() error { - return p.Fs().RemoveAll(p.String()) -} - -// RenameStr renames a file -func (p *Path) RenameStr(newname string) error { - if err := p.Fs().Rename(p.String(), newname); err != nil { - return err - } - - // Rename succeeded. Set our path to the newname. - p.path = newname - return nil -} - -// Rename renames a file -func (p *Path) Rename(target *Path) error { - return p.RenameStr(target.String()) -} - -// Stat returns the os.FileInfo of the given path -func (p *Path) Stat() (os.FileInfo, error) { - return p.Fs().Stat(p.String()) -} - -// Chmod changes the file mode of the given path -func (p *Path) Chmod(mode os.FileMode) error { - return p.Fs().Chmod(p.String(), mode) -} - -// Chtimes changes the modification and access time of the given path. -func (p *Path) Chtimes(atime time.Time, mtime time.Time) error { - return p.Fs().Chtimes(p.String(), atime, mtime) -} - -// ************************ -// * afero.Afero wrappers * -// ************************ - -// DirExists returns whether or not the path represents a directory that exists -func (p *Path) DirExists() (bool, error) { - return afero.DirExists(p.Fs(), p.String()) -} - -// Exists returns whether the path exists -func (p *Path) Exists() (bool, error) { - return afero.Exists(p.Fs(), p.String()) -} - -// FileContainsAnyBytes returns whether or not the path contains -// any of the listed bytes. -func (p *Path) FileContainsAnyBytes(subslices [][]byte) (bool, error) { - return afero.FileContainsAnyBytes(p.Fs(), p.String(), subslices) -} - -// FileContainsBytes returns whether or not the given file contains the bytes -func (p *Path) FileContainsBytes(subslice []byte) (bool, error) { - return afero.FileContainsBytes(p.Fs(), p.String(), subslice) -} - -// IsDir checks if a given path is a directory. -func (p *Path) IsDir() (bool, error) { - return afero.IsDir(p.Fs(), p.String()) -} - -// IsDir returns whether or not the os.FileMode object represents a -// directory. -func IsDir(mode os.FileMode) bool { - return mode.IsDir() -} - -// IsEmpty checks if a given file or directory is empty. -func (p *Path) IsEmpty() (bool, error) { - return afero.IsEmpty(p.Fs(), p.String()) -} - -// ReadDir reads the current path and returns a list of the corresponding -// Path objects. This function differs from os.Readdir in that it does -// not call Stat() on the files. Instead, it calls Readdirnames which -// is less expensive and does not force the caller to make expensive -// Stat calls. -func (p *Path) ReadDir() ([]*Path, error) { - paths := []*Path{} - handle, err := p.Open() - if err != nil { - return paths, err - } - children, err := handle.Readdirnames(-1) - if err != nil { - return paths, err - } - for _, child := range children { - paths = append(paths, p.Join(child)) - } - return paths, err -} - -// ReadFile reads the given path and returns the data. If the file doesn't exist -// or is a directory, an error is returned. -func (p *Path) ReadFile() ([]byte, error) { - return afero.ReadFile(p.Fs(), p.String()) -} - -// SafeWriteReader is the same as WriteReader but checks to see if file/directory already exists. -func (p *Path) SafeWriteReader(r io.Reader) error { - return afero.SafeWriteReader(p.Fs(), p.String(), r) -} - -// WriteFileMode writes the given data to the path (if possible). If the file exists, -// the file is truncated. If the file is a directory, or the path doesn't exist, -// an error is returned. -func (p *Path) WriteFileMode(data []byte, perm os.FileMode) error { - return afero.WriteFile(p.Fs(), p.String(), data, perm) -} - -// WriteFile writes the given data to the path (if possible). If the file exists, -// the file is truncated. If the file is a directory, or the path doesn't exist, -// an error is returned. -func (p *Path) WriteFile(data []byte) error { - return afero.WriteFile(p.Fs(), p.String(), data, p.DefaultFileMode) -} - -// WriteReader takes a reader and writes the content -func (p *Path) WriteReader(r io.Reader) error { - return afero.WriteReader(p.Fs(), p.String(), r) -} - -// ************************************* -// * pathlib.Path-like implementations * -// ************************************* - -// Name returns the string representing the final path component -func (p *Path) Name() string { - return filepath.Base(p.path) -} - -// Parent returns the Path object of the parent directory -func (p *Path) Parent() *Path { - return NewPathAfero(filepath.Dir(p.String()), p.Fs()) -} - -// Readlink returns the target path of a symlink. -// -// This will fail if the underlying afero filesystem does not implement -// afero.LinkReader. -func (p *Path) Readlink() (*Path, error) { - linkReader, ok := p.Fs().(afero.LinkReader) - if !ok { - return nil, p.doesNotImplementErr("afero.LinkReader") - } - - resolvedPathStr, err := linkReader.ReadlinkIfPossible(p.path) - if err != nil { - return nil, err - } - return NewPathAfero(resolvedPathStr, p.fs), nil -} - -func resolveIfSymlink(path *Path) (*Path, bool, error) { - isSymlink, err := path.IsSymlink() - if err != nil { - return path, isSymlink, err - } - if isSymlink { - resolvedPath, err := path.Readlink() - if err != nil { - // Return the path unchanged on errors - return path, isSymlink, err - } - return resolvedPath, isSymlink, nil - } - return path, isSymlink, nil -} - -func resolveAllHelper(path *Path) (*Path, error) { - parts := path.Parts() - - for i := 0; i < len(parts); i++ { - rightOfComponent := parts[i+1:] - upToComponent := parts[:i+1] - - componentPath := NewPathAfero(strings.Join(upToComponent, path.Sep), path.Fs()) - resolved, isSymlink, err := resolveIfSymlink(componentPath) - if err != nil { - return path, err - } - - if isSymlink { - if resolved.IsAbsolute() { - return resolveAllHelper(resolved.Join(strings.Join(rightOfComponent, path.Sep))) - } - return resolveAllHelper(componentPath.Parent().JoinPath(resolved).Join(rightOfComponent...)) - } - } - - // If we get through the entire iteration above, that means no component was a symlink. - // Return the argument. - return path, nil -} - -// ResolveAll canonicalizes the path by following every symlink in -// every component of the given path recursively. The behavior -// should be identical to the `readlink -f` command from POSIX OSs. -// This will fail if the underlying afero filesystem does not implement -// afero.LinkReader. The path will be returned unchanged on errors. -func (p *Path) ResolveAll() (*Path, error) { - return resolveAllHelper(p) -} - -// Parts returns the individual components of a path -func (p *Path) Parts() []string { - parts := []string{} - if p.IsAbsolute() { - parts = append(parts, p.Sep) - } - normalizedPathStr := normalizePathString(p.String()) - normalizedParts := normalizePathParts(strings.Split(normalizedPathStr, p.Sep)) - return append(parts, normalizedParts...) -} - -// IsAbsolute returns whether or not the path is an absolute path. This is -// determined by checking if the path starts with a slash. -func (p *Path) IsAbsolute() bool { - return strings.HasPrefix(p.path, "/") -} - -// Join joins the current object's path with the given elements and returns -// the resulting Path object. -func (p *Path) Join(elems ...string) *Path { - paths := []string{p.path} - paths = append(paths, elems...) - return NewPathAfero(strings.Join(paths, p.Sep), p.Fs()) -} - -// JoinPath is the same as Join() except it accepts a path object -func (p *Path) JoinPath(path *Path) *Path { - return p.Join(path.Parts()...) -} - -func normalizePathString(path string) string { - path = strings.TrimSpace(path) - path = strings.TrimPrefix(path, "./") - path = strings.TrimRight(path, " ") - if len(path) > 1 { - path = strings.TrimSuffix(path, "/") - } - return path -} - -func normalizePathParts(path []string) []string { - // We might encounter cases where path represents a split of the path - // "///" etc. We will get a bunch of erroneous empty strings in such a split, - // so remove all of the trailing empty strings except for the first one (if any) - normalized := []string{} - for i := 0; i < len(path); i++ { - if path[i] != "" { - normalized = append(normalized, path[i]) - } - } - return normalized -} - -// RelativeTo computes a relative version of path to the other path. For instance, -// if the object is /path/to/foo.txt and you provide /path/ as the argment, the -// returned Path object will represent to/foo.txt. -func (p *Path) RelativeTo(other *Path) (*Path, error) { - thisPathNormalized := normalizePathString(p.String()) - otherPathNormalized := normalizePathString(other.String()) - - thisParts := p.Parts() - otherParts := other.Parts() - - var relativeBase int - for idx, part := range otherParts { - if idx >= len(thisParts) || thisParts[idx] != part { - return p, fmt.Errorf("%s does not start with %s: %w", thisPathNormalized, otherPathNormalized, ErrRelativeTo) - } - relativeBase = idx - } - - relativePath := thisParts[relativeBase+1:] - - if len(relativePath) == 0 || (len(relativePath) == 1 && relativePath[0] == "") { - relativePath = []string{"."} - } - - return NewPathAfero(strings.Join(relativePath, "/"), p.Fs()), nil -} - -// RelativeToStr computes a relative version of path to the other path. For instance, -// if the object is /path/to/foo.txt and you provide /path/ as the argment, the -// returned Path object will represent to/foo.txt. -func (p *Path) RelativeToStr(other string) (*Path, error) { - return p.RelativeTo(NewPathAfero(other, p.Fs())) -} - -// Lstat lstat's the path if the underlying afero filesystem supports it. If -// the filesystem does not support afero.Lstater, or if the filesystem implements -// afero.Lstater but returns false for the "lstat called" return value. -// -// A nil os.FileInfo is returned on errors. -func (p *Path) Lstat() (os.FileInfo, error) { - lStater, ok := p.Fs().(afero.Lstater) - if !ok { - return nil, p.doesNotImplementErr("afero.Lstater") - } - stat, lstatCalled, err := lStater.LstatIfPossible(p.String()) - if !lstatCalled && err == nil { - return nil, p.lstatNotPossible() - } - return stat, err -} - -// SymlinkStr symlinks to the target location. This will fail if the underlying -// afero filesystem does not implement afero.Linker. -func (p *Path) SymlinkStr(target string) error { - return p.Symlink(NewPathAfero(target, p.Fs())) -} - -// Symlink symlinks to the target location. This will fail if the underlying -// afero filesystem does not implement afero.Linker. -func (p *Path) Symlink(target *Path) error { - symlinker, ok := p.fs.(afero.Linker) - if !ok { - return p.doesNotImplementErr("afero.Linker") - } - - return symlinker.SymlinkIfPossible(target.path, p.path) -} - -// String returns the string representation of the path -func (p *Path) String() string { - return p.path -} - -// IsFile returns true if the given path is a file. -func (p *Path) IsFile() (bool, error) { - fileInfo, err := p.Stat() - if err != nil { - return false, err - } - return IsFile(fileInfo.Mode()), nil -} - -// IsFile returns whether or not the file described by the given -// os.FileMode is a regular file. -func IsFile(mode os.FileMode) bool { - return mode.IsRegular() -} - -// IsSymlink returns true if the given path is a symlink. -// Fails if the filesystem doesn't implement afero.Lstater. -func (p *Path) IsSymlink() (bool, error) { - fileInfo, err := p.Lstat() - if err != nil { - return false, err - } - return IsSymlink(fileInfo.Mode()), nil -} - -// IsSymlink returns true if the file described by the given -// os.FileMode describes a symlink. -func IsSymlink(mode os.FileMode) bool { - return mode&os.ModeSymlink != 0 -} - -// DeepEquals returns whether or not the path pointed to by other -// has the same resolved filepath as self. -func (p *Path) DeepEquals(other *Path) (bool, error) { - selfResolved, err := p.ResolveAll() - if err != nil { - return false, err - } - otherResolved, err := other.ResolveAll() - if err != nil { - return false, err - } - - return selfResolved.Clean().Equals(otherResolved.Clean()), nil -} - -// Equals returns whether or not the object's path is identical -// to other's, in a shallow sense. It simply checks for equivalence -// in the unresolved Paths() of each object. -func (p *Path) Equals(other *Path) bool { - return p.String() == other.String() -} - -// GetLatest returns the file or directory that has the most recent mtime. Only -// works if this path is a directory and it exists. If the directory is empty, -// the returned Path object will be nil. -func (p *Path) GetLatest() (*Path, error) { - files, err := p.ReadDir() - if err != nil { - return nil, err - } - - var greatestFileSeen *Path - for _, file := range files { - if greatestFileSeen == nil { - greatestFileSeen = p.Join(file.Name()) - } - - greatestMtime, err := greatestFileSeen.Mtime() - if err != nil { - return nil, err - } - - thisMtime, err := file.Mtime() - // There is a possible race condition where the file is deleted after - // our call to ReadDir. We throw away the error if it isn't - // os.ErrNotExist - if err != nil && !os.IsNotExist(err) { - return nil, err - } - if thisMtime.After(greatestMtime) { - greatestFileSeen = p.Join(file.Name()) - } - } - - return greatestFileSeen, nil -} - -// Glob returns all matches of pattern relative to this object's path. -func (p *Path) Glob(pattern string) ([]*Path, error) { - return Glob(p.Fs(), p.Join(pattern).String()) -} - -// Clean returns a new object that is a lexically-cleaned -// version of Path. -func (p *Path) Clean() *Path { - return NewPathAfero(filepath.Clean(p.String()), p.Fs()) -} - -// Mtime returns the modification time of the given path. -func (p *Path) Mtime() (time.Time, error) { - stat, err := p.Stat() - if err != nil { - return time.Time{}, err - } - return Mtime(stat) -} - -// Copy copies the path to another path using io.Copy. -// Returned is the number of bytes copied and any error values. -// The destination file is truncated if it exists, and is created -// if it does not exist. -func (p *Path) Copy(other *Path) (int64, error) { - srcFile, err := p.Open() - if err != nil { - return 0, fmt.Errorf("opening source file: %w", err) - } - defer srcFile.Close() - dstFile, err := other.OpenFile(os.O_TRUNC | os.O_CREATE | os.O_WRONLY) - if err != nil { - return 0, fmt.Errorf("opening destination file: %w", err) - } - defer dstFile.Close() - return io.Copy(dstFile, srcFile) -} - -// Mtime returns the mtime described in the given os.FileInfo object -func Mtime(fileInfo os.FileInfo) (time.Time, error) { - return fileInfo.ModTime(), nil -} - -// Size returns the size of the object. Fails if the object doesn't exist. -func (p *Path) Size() (int64, error) { - stat, err := p.Stat() - if err != nil { - return 0, err - } - return Size(stat), nil -} - -// Size returns the size described by the os.FileInfo. Before you say anything, -// yes... you could just do fileInfo.Size(). This is purely a convenience function -// to create API consistency. -func Size(fileInfo os.FileInfo) int64 { - return fileInfo.Size() -} diff --git a/vendor/github.com/chigopher/pathlib/vars.go b/vendor/github.com/chigopher/pathlib/vars.go deleted file mode 100644 index 138eba428..000000000 --- a/vendor/github.com/chigopher/pathlib/vars.go +++ /dev/null @@ -1,9 +0,0 @@ -package pathlib - -import "os" - -// DefaultFileMode is the file mode that will be applied to new pathlib files -var DefaultFileMode = os.FileMode(0o644) - -// DefaultDirMode is the default mode that will be applied to new directories -var DefaultDirMode = os.FileMode(0o755) diff --git a/vendor/github.com/chigopher/pathlib/walk.go b/vendor/github.com/chigopher/pathlib/walk.go deleted file mode 100644 index c50a9c938..000000000 --- a/vendor/github.com/chigopher/pathlib/walk.go +++ /dev/null @@ -1,405 +0,0 @@ -package pathlib - -import ( - "errors" - "fmt" - "os" - "slices" -) - -// WalkOpts is the struct that defines how a walk should be performed -type WalkOpts struct { - // Depth defines how far down a directory we should recurse. A value of -1 means - // infinite depth. 0 means only the direct children of root will be returned, etc. - Depth int - - // Algorithm specifies the algoritm that the Walk() function should use to - // traverse the directory. - Algorithm Algorithm - - // FollowSymlinks defines whether symlinks should be dereferenced or not. If True, - // the symlink itself will never be returned to WalkFunc, but rather whatever it - // points to. - FollowSymlinks bool - - // MinimumFileSize specifies the minimum size of a file for visitation. - // If negative, there is no minimum size. - MinimumFileSize int64 - - // MaximumFileSize specifies the maximum size of a file for visitation. - // If negative, there is no maximum size. - MaximumFileSize int64 - - // VisitFiles specifies that we should visit regular files during - // the walk. - VisitFiles bool - - // VisitDirs specifies that we should visit directories during the walk. - VisitDirs bool - - // VisitSymlinks specifies that we should visit symlinks during the walk. - VisitSymlinks bool - - // SortChildren causes all children of a path to be lexigraphically sorted before - // being sent to the WalkFunc. - SortChildren bool -} - -// DefaultWalkOpts returns the default WalkOpts struct used when -// walking a directory. -func DefaultWalkOpts() *WalkOpts { - return &WalkOpts{ - Depth: -1, - Algorithm: AlgorithmBasic, - FollowSymlinks: false, - MinimumFileSize: -1, - MaximumFileSize: -1, - VisitFiles: true, - VisitDirs: true, - VisitSymlinks: true, - SortChildren: false, - } -} - -// MeetsMinimumSize returns whether size is at least the minimum specified. -func (w *WalkOpts) MeetsMinimumSize(size int64) bool { - if w.MinimumFileSize < 0 { - return true - } - return size >= w.MinimumFileSize -} - -// MeetsMaximumSize returns whether size is less than or equal to the maximum specified. -func (w *WalkOpts) MeetsMaximumSize(size int64) bool { - if w.MaximumFileSize < 0 { - return true - } - return size <= w.MaximumFileSize -} - -// Algorithm represents the walk algorithm that will be performed. -type Algorithm int - -const ( - // AlgorithmBasic is a walk algorithm. It iterates over filesystem objects in the - // order in which they are returned by the operating system. It guarantees no - // ordering of any kind. It will recurse into subdirectories as soon as it encounters them, - // and will continue iterating the remaining children after the recursion is complete. - // It behaves as a quasi-DFS algorithm. - AlgorithmBasic Algorithm = iota - // AlgorithmDepthFirst is a walk algorithm. More specifically, it is a post-order - // depth first search whereby subdirectories are recursed into before - // visiting the children of the current directory. - // DEPRECATED: Use AlgorithmPostOrderDepthFirst - AlgorithmDepthFirst - // AlgorithmPostOrderDepthFirst is a walk algorithm that recurses into all of its children - // before visiting any of a node's elements. - AlgorithmPostOrderDepthFirst - // AlgorithmPreOrderDepthFirst is a walk algorithm. It visits all of a node's elements - // before recursing into its children. - AlgorithmPreOrderDepthFirst -) - -// Walk is an object that handles walking through a directory tree -type Walk struct { - Opts *WalkOpts - root *Path -} - -type WalkOptsFunc func(config *WalkOpts) - -func WalkDepth(depth int) WalkOptsFunc { - return func(config *WalkOpts) { - config.Depth = depth - } -} - -func WalkAlgorithm(algo Algorithm) WalkOptsFunc { - return func(config *WalkOpts) { - config.Algorithm = algo - } -} - -func WalkFollowSymlinks(follow bool) WalkOptsFunc { - return func(config *WalkOpts) { - config.FollowSymlinks = follow - } -} - -func WalkMinimumFileSize(size int64) WalkOptsFunc { - return func(config *WalkOpts) { - config.MinimumFileSize = size - } -} - -func WalkMaximumFileSize(size int64) WalkOptsFunc { - return func(config *WalkOpts) { - config.MaximumFileSize = size - } -} - -func WalkVisitFiles(value bool) WalkOptsFunc { - return func(config *WalkOpts) { - config.VisitFiles = value - } -} - -func WalkVisitDirs(value bool) WalkOptsFunc { - return func(config *WalkOpts) { - config.VisitDirs = value - } -} - -func WalkVisitSymlinks(value bool) WalkOptsFunc { - return func(config *WalkOpts) { - config.VisitSymlinks = value - } -} - -func WalkSortChildren(value bool) WalkOptsFunc { - return func(config *WalkOpts) { - config.SortChildren = value - } -} - -// NewWalk returns a new Walk struct with default values applied -func NewWalk(root *Path, opts ...WalkOptsFunc) (*Walk, error) { - config := DefaultWalkOpts() - for _, opt := range opts { - opt(config) - } - return NewWalkWithOpts(root, config) -} - -// NewWalkWithOpts returns a Walk object with the given WalkOpts applied -func NewWalkWithOpts(root *Path, opts *WalkOpts) (*Walk, error) { - if root == nil { - return nil, fmt.Errorf("root path can't be nil") - } - if opts == nil { - return nil, fmt.Errorf("opts can't be nil") - } - return &Walk{ - Opts: opts, - root: root, - }, nil -} - -func (w *Walk) maxDepthReached(currentDepth int) bool { - if w.Opts.Depth >= 0 && currentDepth > w.Opts.Depth { - return true - } - return false -} - -type dfsObjectInfo struct { - path *Path - info os.FileInfo - err error -} - -func (w *Walk) walkDFS(walkFn WalkFunc, root *Path, currentDepth int) error { - if w.maxDepthReached(currentDepth) { - return nil - } - - var children []*dfsObjectInfo - - if err := w.iterateImmediateChildren(root, func(child *Path, info os.FileInfo, encounteredErr error) error { - // Since we are doing depth-first, we have to first recurse through all the directories, - // and save all non-directory objects so we can defer handling at a later time. - if IsDir(info.Mode()) { - if err := w.walkDFS(walkFn, child, currentDepth+1); err != nil && !errors.Is(err, ErrWalkSkipSubtree) { - return err - } - } - - children = append(children, &dfsObjectInfo{ - path: child, - info: info, - err: encounteredErr, - }) - - return nil - }); err != nil { - return err - } - - // Iterate over all children after all subdirs have been recursed - for _, child := range children { - passesQuery, err := w.passesQuerySpecification(child.info) - if err != nil { - return err - } - - if passesQuery { - if err := walkFn(child.path, child.info, child.err); err != nil { - return err - } - } - - } - return nil -} - -// iterateImmediateChildren is a function that handles discovering root's immediate children, -// and will run the algorithm function for every child. The algorithm function is essentially -// what differentiates how each walk behaves, and determines what actions to take given a -// certain child. -func (w *Walk) iterateImmediateChildren(root *Path, algorithmFunction WalkFunc) error { - children, err := root.ReadDir() - if err != nil { - return err - } - - if w.Opts.SortChildren { - slices.SortFunc[[]*Path, *Path](children, func(a *Path, b *Path) int { - if a.String() < b.String() { - return -1 - } - if a.String() == b.String() { - return 0 - } - return 1 - }) - } - var info os.FileInfo - for _, child := range children { - if child.String() == root.String() { - continue - } - if w.Opts.FollowSymlinks { - info, err = child.Stat() - if err != nil { - return err - } - } else { - info, err = child.Lstat() - } - - if info == nil { - if err != nil { - return err - } - return ErrInfoIsNil - } - - if algoErr := algorithmFunction(child, info, err); algoErr != nil { - return algoErr - } - } - return nil -} - -// passesQuerySpecification returns whether or not the object described by -// the os.FileInfo passes all of the query specifications listed in -// the walk options. -func (w *Walk) passesQuerySpecification(info os.FileInfo) (bool, error) { - if IsFile(info.Mode()) { - if !w.Opts.VisitFiles { - return false, nil - } - - if !w.Opts.MeetsMinimumSize(info.Size()) || - !w.Opts.MeetsMaximumSize(info.Size()) { - return false, nil - } - } else if IsDir(info.Mode()) && !w.Opts.VisitDirs { - return false, nil - } else if IsSymlink(info.Mode()) && !w.Opts.VisitSymlinks { - return false, nil - } - - return true, nil -} - -func (w *Walk) walkBasic(walkFn WalkFunc, root *Path, currentDepth int) error { - if w.maxDepthReached(currentDepth) { - return nil - } - - err := w.iterateImmediateChildren(root, func(child *Path, info os.FileInfo, encounteredErr error) error { - if IsDir(info.Mode()) { - // In the case the error is ErrWalkSkipSubtree, we ignore it as we've already - // exited from the recursive call. Any other error should be bubbled up. - if err := w.walkBasic(walkFn, child, currentDepth+1); err != nil && !errors.Is(err, ErrWalkSkipSubtree) { - return err - } - } - - passesQuery, err := w.passesQuerySpecification(info) - if err != nil { - return err - } - - if passesQuery { - if err := walkFn(child, info, encounteredErr); err != nil { - return err - } - } - - return nil - }) - - return err -} - -func (w *Walk) walkPreOrderDFS(walkFn WalkFunc, root *Path, currentDepth int) error { - if w.maxDepthReached(currentDepth) { - return nil - } - dirs := []*Path{} - err := w.iterateImmediateChildren(root, func(child *Path, info os.FileInfo, encounteredErr error) error { - if IsDir(info.Mode()) { - dirs = append(dirs, child) - } - - passesQuery, err := w.passesQuerySpecification(info) - if err != nil { - return err - } - - if passesQuery { - if err := walkFn(child, info, encounteredErr); err != nil { - return err - } - } - return nil - }) - if err != nil { - return err - } - for _, dir := range dirs { - if err := w.walkPreOrderDFS(walkFn, dir, currentDepth+1); err != nil && !errors.Is(err, ErrWalkSkipSubtree) { - return err - } - } - return nil -} - -// WalkFunc is the function provided to the Walk function for each directory. -type WalkFunc func(path *Path, info os.FileInfo, err error) error - -// Walk walks the directory using the algorithm specified in the configuration. Your WalkFunc -// may return any of the ErrWalk* errors to control various behavior of the walker. See the documentation -// of each error for more details. -func (w *Walk) Walk(walkFn WalkFunc) error { - funcs := map[Algorithm]func(walkFn WalkFunc, root *Path, currentDepth int) error{ - AlgorithmBasic: w.walkBasic, - AlgorithmDepthFirst: w.walkDFS, - AlgorithmPostOrderDepthFirst: w.walkDFS, - AlgorithmPreOrderDepthFirst: w.walkPreOrderDFS, - } - algoFunc, ok := funcs[w.Opts.Algorithm] - if !ok { - return ErrInvalidAlgorithm - } - if err := algoFunc(walkFn, w.root, 0); err != nil { - if errors.Is(err, errWalkControl) { - return nil - } - return err - } - return nil - -} -- cgit mrf-deployment