mirror of
				https://github.com/optim-enterprises-bv/kubernetes.git
				synced 2025-11-04 04:08:16 +00:00 
			
		
		
		
	remove fakefs to drop spf13/afero dependency
Signed-off-by: Davanum Srinivas <davanum@gmail.com>
This commit is contained in:
		
							
								
								
									
										178
									
								
								LICENSES/vendor/github.com/spf13/afero/LICENSE
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										178
									
								
								LICENSES/vendor/github.com/spf13/afero/LICENSE
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,178 +0,0 @@
 | 
				
			|||||||
= vendor/github.com/spf13/afero licensed under: =
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                                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.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
= vendor/github.com/spf13/afero/LICENSE.txt 920d76114a32b0fb75b3f2718c5a91be
 | 
					 | 
				
			||||||
@@ -372,7 +372,7 @@ func loadConfigFile(name string) (*kubeletconfiginternal.KubeletConfiguration, e
 | 
				
			|||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, fmt.Errorf(errFmt, name, err)
 | 
							return nil, fmt.Errorf(errFmt, name, err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	loader, err := configfiles.NewFsLoader(utilfs.DefaultFs{}, kubeletConfigFile)
 | 
						loader, err := configfiles.NewFsLoader(&utilfs.DefaultFs{}, kubeletConfigFile)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, fmt.Errorf(errFmt, name, err)
 | 
							return nil, fmt.Errorf(errFmt, name, err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										1
									
								
								go.mod
									
									
									
									
									
								
							
							
						
						
									
										1
									
								
								go.mod
									
									
									
									
									
								
							@@ -77,7 +77,6 @@ require (
 | 
				
			|||||||
	github.com/prometheus/common v0.26.0
 | 
						github.com/prometheus/common v0.26.0
 | 
				
			||||||
	github.com/quobyte/api v0.1.8
 | 
						github.com/quobyte/api v0.1.8
 | 
				
			||||||
	github.com/robfig/cron/v3 v3.0.1
 | 
						github.com/robfig/cron/v3 v3.0.1
 | 
				
			||||||
	github.com/spf13/afero v1.2.2
 | 
					 | 
				
			||||||
	github.com/spf13/cobra v1.1.3
 | 
						github.com/spf13/cobra v1.1.3
 | 
				
			||||||
	github.com/spf13/pflag v1.0.5
 | 
						github.com/spf13/pflag v1.0.5
 | 
				
			||||||
	github.com/storageos/go-api v2.2.0+incompatible
 | 
						github.com/storageos/go-api v2.2.0+incompatible
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -54,7 +54,7 @@ type impl struct {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// NewCheckpointManager returns a new instance of a checkpoint manager
 | 
					// NewCheckpointManager returns a new instance of a checkpoint manager
 | 
				
			||||||
func NewCheckpointManager(checkpointDir string) (CheckpointManager, error) {
 | 
					func NewCheckpointManager(checkpointDir string) (CheckpointManager, error) {
 | 
				
			||||||
	fstore, err := utilstore.NewFileStore(checkpointDir, utilfs.DefaultFs{})
 | 
						fstore, err := utilstore.NewFileStore(checkpointDir, &utilfs.DefaultFs{})
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -41,7 +41,7 @@ import (
 | 
				
			|||||||
func newInitializedFakeFsStore() (*fsStore, error) {
 | 
					func newInitializedFakeFsStore() (*fsStore, error) {
 | 
				
			||||||
	// Test with the default filesystem, the fake filesystem has an issue caused by afero: https://github.com/spf13/afero/issues/141
 | 
						// Test with the default filesystem, the fake filesystem has an issue caused by afero: https://github.com/spf13/afero/issues/141
 | 
				
			||||||
	// The default filesystem also behaves more like production, so we should probably not mock the filesystem for unit tests.
 | 
						// The default filesystem also behaves more like production, so we should probably not mock the filesystem for unit tests.
 | 
				
			||||||
	fs := utilfs.DefaultFs{}
 | 
						fs := &utilfs.DefaultFs{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	tmpDir, err := fs.TempDir("", "fsstore-test-")
 | 
						tmpDir, err := fs.TempDir("", "fsstore-test-")
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -152,7 +152,8 @@ foo: bar`),
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	for _, c := range cases {
 | 
						for _, c := range cases {
 | 
				
			||||||
		t.Run(c.desc, func(t *testing.T) {
 | 
							t.Run(c.desc, func(t *testing.T) {
 | 
				
			||||||
			fs := utilfs.NewFakeFs()
 | 
								fs := utilfs.NewTempFs()
 | 
				
			||||||
 | 
								fs.MkdirAll(configDir, 0777)
 | 
				
			||||||
			path := filepath.Join(configDir, kubeletFile)
 | 
								path := filepath.Join(configDir, kubeletFile)
 | 
				
			||||||
			if c.file != nil {
 | 
								if c.file != nil {
 | 
				
			||||||
				if err := addFile(fs, path, *c.file); err != nil {
 | 
									if err := addFile(fs, path, *c.file); err != nil {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -90,7 +90,7 @@ func NewController(dynamicConfigDir string, transform TransformFunc) *Controller
 | 
				
			|||||||
		// channels must have capacity at least 1, since we signal with non-blocking writes
 | 
							// channels must have capacity at least 1, since we signal with non-blocking writes
 | 
				
			||||||
		pendingConfigSource: make(chan bool, 1),
 | 
							pendingConfigSource: make(chan bool, 1),
 | 
				
			||||||
		configStatus:        status.NewNodeConfigStatus(),
 | 
							configStatus:        status.NewNodeConfigStatus(),
 | 
				
			||||||
		checkpointStore:     store.NewFsStore(utilfs.DefaultFs{}, filepath.Join(dynamicConfigDir, storeDir)),
 | 
							checkpointStore:     store.NewFsStore(&utilfs.DefaultFs{}, filepath.Join(dynamicConfigDir, storeDir)),
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -205,7 +205,7 @@ func TestHelpers(t *testing.T) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	for _, c := range cases {
 | 
						for _, c := range cases {
 | 
				
			||||||
		t.Run(c.desc, func(t *testing.T) {
 | 
							t.Run(c.desc, func(t *testing.T) {
 | 
				
			||||||
			c.run(t, utilfs.DefaultFs{})
 | 
								c.run(t, &utilfs.DefaultFs{})
 | 
				
			||||||
		})
 | 
							})
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -241,7 +241,7 @@ func TestFileExists(t *testing.T) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	for _, c := range cases {
 | 
						for _, c := range cases {
 | 
				
			||||||
		t.Run(c.desc, func(t *testing.T) {
 | 
							t.Run(c.desc, func(t *testing.T) {
 | 
				
			||||||
			c.run(t, utilfs.DefaultFs{})
 | 
								c.run(t, &utilfs.DefaultFs{})
 | 
				
			||||||
		})
 | 
							})
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -276,7 +276,7 @@ func TestEnsureFile(t *testing.T) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	for _, c := range cases {
 | 
						for _, c := range cases {
 | 
				
			||||||
		t.Run(c.desc, func(t *testing.T) {
 | 
							t.Run(c.desc, func(t *testing.T) {
 | 
				
			||||||
			c.run(t, utilfs.DefaultFs{})
 | 
								c.run(t, &utilfs.DefaultFs{})
 | 
				
			||||||
		})
 | 
							})
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -317,7 +317,7 @@ func TestReplaceFile(t *testing.T) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	for _, c := range cases {
 | 
						for _, c := range cases {
 | 
				
			||||||
		t.Run(c.desc, func(t *testing.T) {
 | 
							t.Run(c.desc, func(t *testing.T) {
 | 
				
			||||||
			c.run(t, utilfs.DefaultFs{})
 | 
								c.run(t, &utilfs.DefaultFs{})
 | 
				
			||||||
		})
 | 
							})
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -353,7 +353,7 @@ func TestDirExists(t *testing.T) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	for _, c := range cases {
 | 
						for _, c := range cases {
 | 
				
			||||||
		t.Run(c.desc, func(t *testing.T) {
 | 
							t.Run(c.desc, func(t *testing.T) {
 | 
				
			||||||
			c.run(t, utilfs.DefaultFs{})
 | 
								c.run(t, &utilfs.DefaultFs{})
 | 
				
			||||||
		})
 | 
							})
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -388,7 +388,7 @@ func TestEnsureDir(t *testing.T) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	for _, c := range cases {
 | 
						for _, c := range cases {
 | 
				
			||||||
		t.Run(c.desc, func(t *testing.T) {
 | 
							t.Run(c.desc, func(t *testing.T) {
 | 
				
			||||||
			c.run(t, utilfs.DefaultFs{})
 | 
								c.run(t, &utilfs.DefaultFs{})
 | 
				
			||||||
		})
 | 
							})
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -405,7 +405,7 @@ func TestWriteTempDir(t *testing.T) {
 | 
				
			|||||||
			return nil
 | 
								return nil
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	c.run(t, utilfs.DefaultFs{})
 | 
						c.run(t, &utilfs.DefaultFs{})
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func TestReplaceDir(t *testing.T) {
 | 
					func TestReplaceDir(t *testing.T) {
 | 
				
			||||||
@@ -471,7 +471,7 @@ func TestReplaceDir(t *testing.T) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	for _, c := range cases {
 | 
						for _, c := range cases {
 | 
				
			||||||
		t.Run(c.desc, func(t *testing.T) {
 | 
							t.Run(c.desc, func(t *testing.T) {
 | 
				
			||||||
			c.run(t, utilfs.DefaultFs{})
 | 
								c.run(t, &utilfs.DefaultFs{})
 | 
				
			||||||
		})
 | 
							})
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -17,8 +17,6 @@ limitations under the License.
 | 
				
			|||||||
package store
 | 
					package store
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"io/ioutil"
 | 
					 | 
				
			||||||
	"os"
 | 
					 | 
				
			||||||
	"sort"
 | 
						"sort"
 | 
				
			||||||
	"testing"
 | 
						"testing"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -28,16 +26,7 @@ import (
 | 
				
			|||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func TestFileStore(t *testing.T) {
 | 
					func TestFileStore(t *testing.T) {
 | 
				
			||||||
	path, err := ioutil.TempDir("", "FileStore")
 | 
						store, err := NewFileStore("/FileStore", filesystem.NewTempFs())
 | 
				
			||||||
	assert.NoError(t, err)
 | 
					 | 
				
			||||||
	defer os.RemoveAll(path)
 | 
					 | 
				
			||||||
	store, err := NewFileStore(path, filesystem.DefaultFs{})
 | 
					 | 
				
			||||||
	assert.NoError(t, err)
 | 
					 | 
				
			||||||
	testStore(t, store)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func TestFakeFileStore(t *testing.T) {
 | 
					 | 
				
			||||||
	store, err := NewFileStore("/tmp/test-fake-file-store", filesystem.NewFakeFs())
 | 
					 | 
				
			||||||
	assert.NoError(t, err)
 | 
						assert.NoError(t, err)
 | 
				
			||||||
	testStore(t, store)
 | 
						testStore(t, store)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -20,22 +20,43 @@ import (
 | 
				
			|||||||
	"io/ioutil"
 | 
						"io/ioutil"
 | 
				
			||||||
	"os"
 | 
						"os"
 | 
				
			||||||
	"path/filepath"
 | 
						"path/filepath"
 | 
				
			||||||
 | 
						"strings"
 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// DefaultFs implements Filesystem using same-named functions from "os" and "io/ioutil"
 | 
					// DefaultFs implements Filesystem using same-named functions from "os" and "io/ioutil"
 | 
				
			||||||
type DefaultFs struct{}
 | 
					type DefaultFs struct {
 | 
				
			||||||
 | 
						root string
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var _ Filesystem = DefaultFs{}
 | 
					var _ Filesystem = &DefaultFs{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// NewTempFs returns a fake Filesystem in temporary directory, useful for unit tests
 | 
				
			||||||
 | 
					func NewTempFs() Filesystem {
 | 
				
			||||||
 | 
						path, _ := ioutil.TempDir(
 | 
				
			||||||
 | 
							"",
 | 
				
			||||||
 | 
							"tmpfs",
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
						return &DefaultFs{
 | 
				
			||||||
 | 
							root: path,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (fs *DefaultFs) prefix(path string) string {
 | 
				
			||||||
 | 
						if len(fs.root) == 0 {
 | 
				
			||||||
 | 
							return path
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return filepath.Join(fs.root, path)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Stat via os.Stat
 | 
					// Stat via os.Stat
 | 
				
			||||||
func (DefaultFs) Stat(name string) (os.FileInfo, error) {
 | 
					func (fs *DefaultFs) Stat(name string) (os.FileInfo, error) {
 | 
				
			||||||
	return os.Stat(name)
 | 
						return os.Stat(fs.prefix(name))
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Create via os.Create
 | 
					// Create via os.Create
 | 
				
			||||||
func (DefaultFs) Create(name string) (File, error) {
 | 
					func (fs *DefaultFs) Create(name string) (File, error) {
 | 
				
			||||||
	file, err := os.Create(name)
 | 
						file, err := os.Create(fs.prefix(name))
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -43,43 +64,49 @@ func (DefaultFs) Create(name string) (File, error) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Rename via os.Rename
 | 
					// Rename via os.Rename
 | 
				
			||||||
func (DefaultFs) Rename(oldpath, newpath string) error {
 | 
					func (fs *DefaultFs) Rename(oldpath, newpath string) error {
 | 
				
			||||||
 | 
						if !strings.HasPrefix(oldpath, fs.root) {
 | 
				
			||||||
 | 
							oldpath = fs.prefix(oldpath)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if !strings.HasPrefix(newpath, fs.root) {
 | 
				
			||||||
 | 
							newpath = fs.prefix(newpath)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	return os.Rename(oldpath, newpath)
 | 
						return os.Rename(oldpath, newpath)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// MkdirAll via os.MkdirAll
 | 
					// MkdirAll via os.MkdirAll
 | 
				
			||||||
func (DefaultFs) MkdirAll(path string, perm os.FileMode) error {
 | 
					func (fs *DefaultFs) MkdirAll(path string, perm os.FileMode) error {
 | 
				
			||||||
	return os.MkdirAll(path, perm)
 | 
						return os.MkdirAll(fs.prefix(path), perm)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Chtimes via os.Chtimes
 | 
					// Chtimes via os.Chtimes
 | 
				
			||||||
func (DefaultFs) Chtimes(name string, atime time.Time, mtime time.Time) error {
 | 
					func (fs *DefaultFs) Chtimes(name string, atime time.Time, mtime time.Time) error {
 | 
				
			||||||
	return os.Chtimes(name, atime, mtime)
 | 
						return os.Chtimes(fs.prefix(name), atime, mtime)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// RemoveAll via os.RemoveAll
 | 
					// RemoveAll via os.RemoveAll
 | 
				
			||||||
func (DefaultFs) RemoveAll(path string) error {
 | 
					func (fs *DefaultFs) RemoveAll(path string) error {
 | 
				
			||||||
	return os.RemoveAll(path)
 | 
						return os.RemoveAll(fs.prefix(path))
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Remove via os.RemoveAll
 | 
					// Remove via os.RemoveAll
 | 
				
			||||||
func (DefaultFs) Remove(name string) error {
 | 
					func (fs *DefaultFs) Remove(name string) error {
 | 
				
			||||||
	return os.Remove(name)
 | 
						return os.Remove(fs.prefix(name))
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// ReadFile via ioutil.ReadFile
 | 
					// ReadFile via ioutil.ReadFile
 | 
				
			||||||
func (DefaultFs) ReadFile(filename string) ([]byte, error) {
 | 
					func (fs *DefaultFs) ReadFile(filename string) ([]byte, error) {
 | 
				
			||||||
	return ioutil.ReadFile(filename)
 | 
						return ioutil.ReadFile(fs.prefix(filename))
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// TempDir via ioutil.TempDir
 | 
					// TempDir via ioutil.TempDir
 | 
				
			||||||
func (DefaultFs) TempDir(dir, prefix string) (string, error) {
 | 
					func (fs *DefaultFs) TempDir(dir, prefix string) (string, error) {
 | 
				
			||||||
	return ioutil.TempDir(dir, prefix)
 | 
						return ioutil.TempDir(fs.prefix(dir), prefix)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// TempFile via ioutil.TempFile
 | 
					// TempFile via ioutil.TempFile
 | 
				
			||||||
func (DefaultFs) TempFile(dir, prefix string) (File, error) {
 | 
					func (fs *DefaultFs) TempFile(dir, prefix string) (File, error) {
 | 
				
			||||||
	file, err := ioutil.TempFile(dir, prefix)
 | 
						file, err := ioutil.TempFile(fs.prefix(dir), prefix)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -87,13 +114,13 @@ func (DefaultFs) TempFile(dir, prefix string) (File, error) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// ReadDir via ioutil.ReadDir
 | 
					// ReadDir via ioutil.ReadDir
 | 
				
			||||||
func (DefaultFs) ReadDir(dirname string) ([]os.FileInfo, error) {
 | 
					func (fs *DefaultFs) ReadDir(dirname string) ([]os.FileInfo, error) {
 | 
				
			||||||
	return ioutil.ReadDir(dirname)
 | 
						return ioutil.ReadDir(fs.prefix(dirname))
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Walk via filepath.Walk
 | 
					// Walk via filepath.Walk
 | 
				
			||||||
func (DefaultFs) Walk(root string, walkFn filepath.WalkFunc) error {
 | 
					func (fs *DefaultFs) Walk(root string, walkFn filepath.WalkFunc) error {
 | 
				
			||||||
	return filepath.Walk(root, walkFn)
 | 
						return filepath.Walk(fs.prefix(root), walkFn)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// defaultFile implements File using same-named functions from "os"
 | 
					// defaultFile implements File using same-named functions from "os"
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,128 +0,0 @@
 | 
				
			|||||||
/*
 | 
					 | 
				
			||||||
Copyright 2017 The Kubernetes Authors.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
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.
 | 
					 | 
				
			||||||
*/
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
package filesystem
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"os"
 | 
					 | 
				
			||||||
	"path/filepath"
 | 
					 | 
				
			||||||
	"time"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	"github.com/spf13/afero"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// fakeFs is implemented in terms of afero
 | 
					 | 
				
			||||||
type fakeFs struct {
 | 
					 | 
				
			||||||
	a afero.Afero
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// NewFakeFs returns a fake Filesystem that exists in-memory, useful for unit tests
 | 
					 | 
				
			||||||
func NewFakeFs() Filesystem {
 | 
					 | 
				
			||||||
	return &fakeFs{a: afero.Afero{Fs: afero.NewMemMapFs()}}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Stat via afero.Fs.Stat
 | 
					 | 
				
			||||||
func (fs *fakeFs) Stat(name string) (os.FileInfo, error) {
 | 
					 | 
				
			||||||
	return fs.a.Fs.Stat(name)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Create via afero.Fs.Create
 | 
					 | 
				
			||||||
func (fs *fakeFs) Create(name string) (File, error) {
 | 
					 | 
				
			||||||
	file, err := fs.a.Fs.Create(name)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return nil, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return &fakeFile{file}, nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Rename via afero.Fs.Rename
 | 
					 | 
				
			||||||
func (fs *fakeFs) Rename(oldpath, newpath string) error {
 | 
					 | 
				
			||||||
	return fs.a.Fs.Rename(oldpath, newpath)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// MkdirAll via afero.Fs.MkdirAll
 | 
					 | 
				
			||||||
func (fs *fakeFs) MkdirAll(path string, perm os.FileMode) error {
 | 
					 | 
				
			||||||
	return fs.a.Fs.MkdirAll(path, perm)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Chtimes via afero.Fs.Chtimes
 | 
					 | 
				
			||||||
func (fs *fakeFs) Chtimes(name string, atime time.Time, mtime time.Time) error {
 | 
					 | 
				
			||||||
	return fs.a.Fs.Chtimes(name, atime, mtime)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// ReadFile via afero.ReadFile
 | 
					 | 
				
			||||||
func (fs *fakeFs) ReadFile(filename string) ([]byte, error) {
 | 
					 | 
				
			||||||
	return fs.a.ReadFile(filename)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// TempDir via afero.TempDir
 | 
					 | 
				
			||||||
func (fs *fakeFs) TempDir(dir, prefix string) (string, error) {
 | 
					 | 
				
			||||||
	return fs.a.TempDir(dir, prefix)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// TempFile via afero.TempFile
 | 
					 | 
				
			||||||
func (fs *fakeFs) TempFile(dir, prefix string) (File, error) {
 | 
					 | 
				
			||||||
	file, err := fs.a.TempFile(dir, prefix)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return nil, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return &fakeFile{file}, nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// ReadDir via afero.ReadDir
 | 
					 | 
				
			||||||
func (fs *fakeFs) ReadDir(dirname string) ([]os.FileInfo, error) {
 | 
					 | 
				
			||||||
	return fs.a.ReadDir(dirname)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Walk via afero.Walk
 | 
					 | 
				
			||||||
func (fs *fakeFs) Walk(root string, walkFn filepath.WalkFunc) error {
 | 
					 | 
				
			||||||
	return fs.a.Walk(root, walkFn)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// RemoveAll via afero.RemoveAll
 | 
					 | 
				
			||||||
func (fs *fakeFs) RemoveAll(path string) error {
 | 
					 | 
				
			||||||
	return fs.a.RemoveAll(path)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Remove via afero.RemoveAll
 | 
					 | 
				
			||||||
func (fs *fakeFs) Remove(name string) error {
 | 
					 | 
				
			||||||
	return fs.a.Remove(name)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// fakeFile implements File; for use with fakeFs
 | 
					 | 
				
			||||||
type fakeFile struct {
 | 
					 | 
				
			||||||
	file afero.File
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Name via afero.File.Name
 | 
					 | 
				
			||||||
func (file *fakeFile) Name() string {
 | 
					 | 
				
			||||||
	return file.file.Name()
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Write via afero.File.Write
 | 
					 | 
				
			||||||
func (file *fakeFile) Write(b []byte) (n int, err error) {
 | 
					 | 
				
			||||||
	return file.file.Write(b)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Sync via afero.File.Sync
 | 
					 | 
				
			||||||
func (file *fakeFile) Sync() error {
 | 
					 | 
				
			||||||
	return file.file.Sync()
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Close via afero.File.Close
 | 
					 | 
				
			||||||
func (file *fakeFile) Close() error {
 | 
					 | 
				
			||||||
	return file.file.Close()
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -19,6 +19,7 @@ package flexvolume
 | 
				
			|||||||
import (
 | 
					import (
 | 
				
			||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
	"path/filepath"
 | 
						"path/filepath"
 | 
				
			||||||
 | 
						"strings"
 | 
				
			||||||
	"testing"
 | 
						"testing"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/fsnotify/fsnotify"
 | 
						"github.com/fsnotify/fsnotify"
 | 
				
			||||||
@@ -33,6 +34,10 @@ const (
 | 
				
			|||||||
	driverName = "fake-driver"
 | 
						driverName = "fake-driver"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func assertPathSuffix(t *testing.T, dir1 string, dir2 string) {
 | 
				
			||||||
 | 
						assert.True(t, strings.HasSuffix(dir2, dir1))
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Probes a driver installed before prober initialization.
 | 
					// Probes a driver installed before prober initialization.
 | 
				
			||||||
func TestProberExistingDriverBeforeInit(t *testing.T) {
 | 
					func TestProberExistingDriverBeforeInit(t *testing.T) {
 | 
				
			||||||
	// Arrange
 | 
						// Arrange
 | 
				
			||||||
@@ -46,8 +51,8 @@ func TestProberExistingDriverBeforeInit(t *testing.T) {
 | 
				
			|||||||
	// current subdirectories) registered.
 | 
						// current subdirectories) registered.
 | 
				
			||||||
	assert.Equal(t, 1, len(events))
 | 
						assert.Equal(t, 1, len(events))
 | 
				
			||||||
	assert.Equal(t, volume.ProbeAddOrUpdate, events[0].Op)
 | 
						assert.Equal(t, volume.ProbeAddOrUpdate, events[0].Op)
 | 
				
			||||||
	assert.Equal(t, pluginDir, watcher.watches[0])
 | 
						assertPathSuffix(t, pluginDir, watcher.watches[0])
 | 
				
			||||||
	assert.Equal(t, driverPath, watcher.watches[1])
 | 
						assertPathSuffix(t, driverPath, watcher.watches[1])
 | 
				
			||||||
	assert.NoError(t, err)
 | 
						assert.NoError(t, err)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Should no longer probe.
 | 
						// Should no longer probe.
 | 
				
			||||||
@@ -84,7 +89,7 @@ func TestProberAddRemoveDriver(t *testing.T) {
 | 
				
			|||||||
	// Assert
 | 
						// Assert
 | 
				
			||||||
	assert.Equal(t, 1, len(events))
 | 
						assert.Equal(t, 1, len(events))
 | 
				
			||||||
	assert.Equal(t, volume.ProbeAddOrUpdate, events[0].Op)                   // 1 newly added
 | 
						assert.Equal(t, volume.ProbeAddOrUpdate, events[0].Op)                   // 1 newly added
 | 
				
			||||||
	assert.Equal(t, driverPath, watcher.watches[len(watcher.watches)-1]) // Checks most recent watch
 | 
						assertPathSuffix(t, driverPath, watcher.watches[len(watcher.watches)-1]) // Checks most recent watch
 | 
				
			||||||
	assert.NoError(t, err)
 | 
						assert.NoError(t, err)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Call probe again, should return 0 event.
 | 
						// Call probe again, should return 0 event.
 | 
				
			||||||
@@ -174,7 +179,7 @@ func TestProberAddRemoveDriver(t *testing.T) {
 | 
				
			|||||||
// Tests the behavior when no drivers exist in the plugin directory.
 | 
					// Tests the behavior when no drivers exist in the plugin directory.
 | 
				
			||||||
func TestEmptyPluginDir(t *testing.T) {
 | 
					func TestEmptyPluginDir(t *testing.T) {
 | 
				
			||||||
	// Arrange
 | 
						// Arrange
 | 
				
			||||||
	fs := utilfs.NewFakeFs()
 | 
						fs := utilfs.NewTempFs()
 | 
				
			||||||
	watcher := newFakeWatcher()
 | 
						watcher := newFakeWatcher()
 | 
				
			||||||
	prober := &flexVolumeProber{
 | 
						prober := &flexVolumeProber{
 | 
				
			||||||
		pluginDir: pluginDir,
 | 
							pluginDir: pluginDir,
 | 
				
			||||||
@@ -205,7 +210,7 @@ func TestRemovePluginDir(t *testing.T) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	// Assert
 | 
						// Assert
 | 
				
			||||||
	assert.Equal(t, 3, len(watcher.watches)) // 2 from initial setup, 1 from new watch.
 | 
						assert.Equal(t, 3, len(watcher.watches)) // 2 from initial setup, 1 from new watch.
 | 
				
			||||||
	assert.Equal(t, pluginDir, watcher.watches[len(watcher.watches)-1])
 | 
						assertPathSuffix(t, pluginDir, watcher.watches[len(watcher.watches)-1])
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Issue an event to remove plugindir. New directory should still be watched.
 | 
					// Issue an event to remove plugindir. New directory should still be watched.
 | 
				
			||||||
@@ -218,22 +223,22 @@ func TestNestedDriverDir(t *testing.T) {
 | 
				
			|||||||
	// test add testDriverName
 | 
						// test add testDriverName
 | 
				
			||||||
	testDriverName := "testDriverName"
 | 
						testDriverName := "testDriverName"
 | 
				
			||||||
	testDriverPath := filepath.Join(pluginDir, testDriverName)
 | 
						testDriverPath := filepath.Join(pluginDir, testDriverName)
 | 
				
			||||||
	fs.MkdirAll(testDriverPath, 0666)
 | 
						fs.MkdirAll(testDriverPath, 0777)
 | 
				
			||||||
	watcher.TriggerEvent(fsnotify.Create, testDriverPath)
 | 
						watcher.TriggerEvent(fsnotify.Create, testDriverPath)
 | 
				
			||||||
	// Assert
 | 
						// Assert
 | 
				
			||||||
	assert.Equal(t, 3, len(watcher.watches)) // 2 from initial setup, 1 from new watch.
 | 
						assert.Equal(t, 3, len(watcher.watches)) // 2 from initial setup, 1 from new watch.
 | 
				
			||||||
	assert.Equal(t, testDriverPath, watcher.watches[len(watcher.watches)-1])
 | 
						assertPathSuffix(t, testDriverPath, watcher.watches[len(watcher.watches)-1])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// test add nested subdir inside testDriverName
 | 
						// test add nested subdir inside testDriverName
 | 
				
			||||||
	basePath := testDriverPath
 | 
						basePath := testDriverPath
 | 
				
			||||||
	for i := 0; i < 10; i++ {
 | 
						for i := 0; i < 10; i++ {
 | 
				
			||||||
		subdirName := "subdirName"
 | 
							subdirName := "subdirName"
 | 
				
			||||||
		subdirPath := filepath.Join(basePath, subdirName)
 | 
							subdirPath := filepath.Join(basePath, subdirName)
 | 
				
			||||||
		fs.MkdirAll(subdirPath, 0666)
 | 
							fs.MkdirAll(subdirPath, 0777)
 | 
				
			||||||
		watcher.TriggerEvent(fsnotify.Create, subdirPath)
 | 
							watcher.TriggerEvent(fsnotify.Create, subdirPath)
 | 
				
			||||||
		// Assert
 | 
							// Assert
 | 
				
			||||||
		assert.Equal(t, 4+i, len(watcher.watches)) // 3 + newly added
 | 
							assert.Equal(t, 4+i, len(watcher.watches)) // 3 + newly added
 | 
				
			||||||
		assert.Equal(t, subdirPath, watcher.watches[len(watcher.watches)-1])
 | 
							assertPathSuffix(t, subdirPath, watcher.watches[len(watcher.watches)-1])
 | 
				
			||||||
		basePath = subdirPath
 | 
							basePath = subdirPath
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -268,7 +273,7 @@ func TestProberMultipleEvents(t *testing.T) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func TestProberError(t *testing.T) {
 | 
					func TestProberError(t *testing.T) {
 | 
				
			||||||
	fs := utilfs.NewFakeFs()
 | 
						fs := utilfs.NewTempFs()
 | 
				
			||||||
	watcher := newFakeWatcher()
 | 
						watcher := newFakeWatcher()
 | 
				
			||||||
	prober := &flexVolumeProber{
 | 
						prober := &flexVolumeProber{
 | 
				
			||||||
		pluginDir: pluginDir,
 | 
							pluginDir: pluginDir,
 | 
				
			||||||
@@ -286,7 +291,7 @@ func TestProberError(t *testing.T) {
 | 
				
			|||||||
// Installs a mock driver (an empty file) in the mock fs.
 | 
					// Installs a mock driver (an empty file) in the mock fs.
 | 
				
			||||||
func installDriver(driverName string, fs utilfs.Filesystem) {
 | 
					func installDriver(driverName string, fs utilfs.Filesystem) {
 | 
				
			||||||
	driverPath := filepath.Join(pluginDir, driverName)
 | 
						driverPath := filepath.Join(pluginDir, driverName)
 | 
				
			||||||
	fs.MkdirAll(driverPath, 0666)
 | 
						fs.MkdirAll(driverPath, 0777)
 | 
				
			||||||
	fs.Create(filepath.Join(driverPath, driverName))
 | 
						fs.Create(filepath.Join(driverPath, driverName))
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -296,7 +301,7 @@ func initTestEnvironment(t *testing.T) (
 | 
				
			|||||||
	fs utilfs.Filesystem,
 | 
						fs utilfs.Filesystem,
 | 
				
			||||||
	watcher *fakeWatcher,
 | 
						watcher *fakeWatcher,
 | 
				
			||||||
	prober volume.DynamicPluginProber) {
 | 
						prober volume.DynamicPluginProber) {
 | 
				
			||||||
	fs = utilfs.NewFakeFs()
 | 
						fs = utilfs.NewTempFs()
 | 
				
			||||||
	watcher = newFakeWatcher()
 | 
						watcher = newFakeWatcher()
 | 
				
			||||||
	prober = &flexVolumeProber{
 | 
						prober = &flexVolumeProber{
 | 
				
			||||||
		pluginDir: pluginDir,
 | 
							pluginDir: pluginDir,
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										21
									
								
								vendor/github.com/spf13/afero/.travis.yml
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										21
									
								
								vendor/github.com/spf13/afero/.travis.yml
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,21 +0,0 @@
 | 
				
			|||||||
sudo: false
 | 
					 | 
				
			||||||
language: go
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
go:
 | 
					 | 
				
			||||||
  - 1.9
 | 
					 | 
				
			||||||
  - "1.10"
 | 
					 | 
				
			||||||
  - tip
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
os:
 | 
					 | 
				
			||||||
  - linux
 | 
					 | 
				
			||||||
  - osx
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
matrix:
 | 
					 | 
				
			||||||
  allow_failures:
 | 
					 | 
				
			||||||
    - go: tip
 | 
					 | 
				
			||||||
  fast_finish: true
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
script:
 | 
					 | 
				
			||||||
  - go build
 | 
					 | 
				
			||||||
  - go test -race -v ./...
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
							
								
								
									
										174
									
								
								vendor/github.com/spf13/afero/LICENSE.txt
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										174
									
								
								vendor/github.com/spf13/afero/LICENSE.txt
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,174 +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.
 | 
					 | 
				
			||||||
							
								
								
									
										452
									
								
								vendor/github.com/spf13/afero/README.md
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										452
									
								
								vendor/github.com/spf13/afero/README.md
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,452 +0,0 @@
 | 
				
			|||||||

 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
A FileSystem Abstraction System for Go
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
[](https://travis-ci.org/spf13/afero) [](https://ci.appveyor.com/project/spf13/afero) [](https://godoc.org/github.com/spf13/afero) [](https://gitter.im/spf13/afero?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Overview
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Afero is an filesystem framework providing a simple, uniform and universal API
 | 
					 | 
				
			||||||
interacting with any filesystem, as an abstraction layer providing interfaces,
 | 
					 | 
				
			||||||
types and methods. Afero has an exceptionally clean interface and simple design
 | 
					 | 
				
			||||||
without needless constructors or initialization methods.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Afero is also a library providing a base set of interoperable backend
 | 
					 | 
				
			||||||
filesystems that make it easy to work with afero while retaining all the power
 | 
					 | 
				
			||||||
and benefit of the os and ioutil packages.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Afero provides significant improvements over using the os package alone, most
 | 
					 | 
				
			||||||
notably the ability to create mock and testing filesystems without relying on the disk.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
It is suitable for use in a any situation where you would consider using the OS
 | 
					 | 
				
			||||||
package as it provides an additional abstraction that makes it easy to use a
 | 
					 | 
				
			||||||
memory backed file system during testing. It also adds support for the http
 | 
					 | 
				
			||||||
filesystem for full interoperability.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
## Afero Features
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
* A single consistent API for accessing a variety of filesystems
 | 
					 | 
				
			||||||
* Interoperation between a variety of file system types
 | 
					 | 
				
			||||||
* A set of interfaces to encourage and enforce interoperability between backends
 | 
					 | 
				
			||||||
* An atomic cross platform memory backed file system
 | 
					 | 
				
			||||||
* Support for compositional (union) file systems by combining multiple file systems acting as one
 | 
					 | 
				
			||||||
* Specialized backends which modify existing filesystems (Read Only, Regexp filtered)
 | 
					 | 
				
			||||||
* A set of utility functions ported from io, ioutil & hugo to be afero aware
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Using Afero
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Afero is easy to use and easier to adopt.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
A few different ways you could use Afero:
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
* Use the interfaces alone to define you own file system.
 | 
					 | 
				
			||||||
* Wrap for the OS packages.
 | 
					 | 
				
			||||||
* Define different filesystems for different parts of your application.
 | 
					 | 
				
			||||||
* Use Afero for mock filesystems while testing
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
## Step 1: Install Afero
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
First use go get to install the latest version of the library.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    $ go get github.com/spf13/afero
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Next include Afero in your application.
 | 
					 | 
				
			||||||
```go
 | 
					 | 
				
			||||||
import "github.com/spf13/afero"
 | 
					 | 
				
			||||||
```
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
## Step 2: Declare a backend
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
First define a package variable and set it to a pointer to a filesystem.
 | 
					 | 
				
			||||||
```go
 | 
					 | 
				
			||||||
var AppFs = afero.NewMemMapFs()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
or
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var AppFs = afero.NewOsFs()
 | 
					 | 
				
			||||||
```
 | 
					 | 
				
			||||||
It is important to note that if you repeat the composite literal you
 | 
					 | 
				
			||||||
will be using a completely new and isolated filesystem. In the case of
 | 
					 | 
				
			||||||
OsFs it will still use the same underlying filesystem but will reduce
 | 
					 | 
				
			||||||
the ability to drop in other filesystems as desired.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
## Step 3: Use it like you would the OS package
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Throughout your application use any function and method like you normally
 | 
					 | 
				
			||||||
would.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
So if my application before had:
 | 
					 | 
				
			||||||
```go
 | 
					 | 
				
			||||||
os.Open('/tmp/foo')
 | 
					 | 
				
			||||||
```
 | 
					 | 
				
			||||||
We would replace it with:
 | 
					 | 
				
			||||||
```go
 | 
					 | 
				
			||||||
AppFs.Open('/tmp/foo')
 | 
					 | 
				
			||||||
```
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
`AppFs` being the variable we defined above.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
## List of all available functions
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
File System Methods Available:
 | 
					 | 
				
			||||||
```go
 | 
					 | 
				
			||||||
Chmod(name string, mode os.FileMode) : error
 | 
					 | 
				
			||||||
Chtimes(name string, atime time.Time, mtime time.Time) : error
 | 
					 | 
				
			||||||
Create(name string) : File, error
 | 
					 | 
				
			||||||
Mkdir(name string, perm os.FileMode) : error
 | 
					 | 
				
			||||||
MkdirAll(path string, perm os.FileMode) : error
 | 
					 | 
				
			||||||
Name() : string
 | 
					 | 
				
			||||||
Open(name string) : File, error
 | 
					 | 
				
			||||||
OpenFile(name string, flag int, perm os.FileMode) : File, error
 | 
					 | 
				
			||||||
Remove(name string) : error
 | 
					 | 
				
			||||||
RemoveAll(path string) : error
 | 
					 | 
				
			||||||
Rename(oldname, newname string) : error
 | 
					 | 
				
			||||||
Stat(name string) : os.FileInfo, error
 | 
					 | 
				
			||||||
```
 | 
					 | 
				
			||||||
File Interfaces and Methods Available:
 | 
					 | 
				
			||||||
```go
 | 
					 | 
				
			||||||
io.Closer
 | 
					 | 
				
			||||||
io.Reader
 | 
					 | 
				
			||||||
io.ReaderAt
 | 
					 | 
				
			||||||
io.Seeker
 | 
					 | 
				
			||||||
io.Writer
 | 
					 | 
				
			||||||
io.WriterAt
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Name() : string
 | 
					 | 
				
			||||||
Readdir(count int) : []os.FileInfo, error
 | 
					 | 
				
			||||||
Readdirnames(n int) : []string, error
 | 
					 | 
				
			||||||
Stat() : os.FileInfo, error
 | 
					 | 
				
			||||||
Sync() : error
 | 
					 | 
				
			||||||
Truncate(size int64) : error
 | 
					 | 
				
			||||||
WriteString(s string) : ret int, err error
 | 
					 | 
				
			||||||
```
 | 
					 | 
				
			||||||
In some applications it may make sense to define a new package that
 | 
					 | 
				
			||||||
simply exports the file system variable for easy access from anywhere.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
## Using Afero's utility functions
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Afero provides a set of functions to make it easier to use the underlying file systems.
 | 
					 | 
				
			||||||
These functions have been primarily ported from io & ioutil with some developed for Hugo.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
The afero utilities support all afero compatible backends.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
The list of utilities includes:
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
```go
 | 
					 | 
				
			||||||
DirExists(path string) (bool, error)
 | 
					 | 
				
			||||||
Exists(path string) (bool, error)
 | 
					 | 
				
			||||||
FileContainsBytes(filename string, subslice []byte) (bool, error)
 | 
					 | 
				
			||||||
GetTempDir(subPath string) string
 | 
					 | 
				
			||||||
IsDir(path string) (bool, error)
 | 
					 | 
				
			||||||
IsEmpty(path string) (bool, error)
 | 
					 | 
				
			||||||
ReadDir(dirname string) ([]os.FileInfo, error)
 | 
					 | 
				
			||||||
ReadFile(filename string) ([]byte, error)
 | 
					 | 
				
			||||||
SafeWriteReader(path string, r io.Reader) (err error)
 | 
					 | 
				
			||||||
TempDir(dir, prefix string) (name string, err error)
 | 
					 | 
				
			||||||
TempFile(dir, prefix string) (f File, err error)
 | 
					 | 
				
			||||||
Walk(root string, walkFn filepath.WalkFunc) error
 | 
					 | 
				
			||||||
WriteFile(filename string, data []byte, perm os.FileMode) error
 | 
					 | 
				
			||||||
WriteReader(path string, r io.Reader) (err error)
 | 
					 | 
				
			||||||
```
 | 
					 | 
				
			||||||
For a complete list see [Afero's GoDoc](https://godoc.org/github.com/spf13/afero)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
They are available under two different approaches to use. You can either call
 | 
					 | 
				
			||||||
them directly where the first parameter of each function will be the file
 | 
					 | 
				
			||||||
system, or you can declare a new `Afero`, a custom type used to bind these
 | 
					 | 
				
			||||||
functions as methods to a given filesystem.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
### Calling utilities directly
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
```go
 | 
					 | 
				
			||||||
fs := new(afero.MemMapFs)
 | 
					 | 
				
			||||||
f, err := afero.TempFile(fs,"", "ioutil-test")
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
```
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
### Calling via Afero
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
```go
 | 
					 | 
				
			||||||
fs := afero.NewMemMapFs()
 | 
					 | 
				
			||||||
afs := &afero.Afero{Fs: fs}
 | 
					 | 
				
			||||||
f, err := afs.TempFile("", "ioutil-test")
 | 
					 | 
				
			||||||
```
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
## Using Afero for Testing
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
There is a large benefit to using a mock filesystem for testing. It has a
 | 
					 | 
				
			||||||
completely blank state every time it is initialized and can be easily
 | 
					 | 
				
			||||||
reproducible regardless of OS. You could create files to your heart’s content
 | 
					 | 
				
			||||||
and the file access would be fast while also saving you from all the annoying
 | 
					 | 
				
			||||||
issues with deleting temporary files, Windows file locking, etc. The MemMapFs
 | 
					 | 
				
			||||||
backend is perfect for testing.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
* Much faster than performing I/O operations on disk
 | 
					 | 
				
			||||||
* Avoid security issues and permissions
 | 
					 | 
				
			||||||
* Far more control. 'rm -rf /' with confidence
 | 
					 | 
				
			||||||
* Test setup is far more easier to do
 | 
					 | 
				
			||||||
* No test cleanup needed
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
One way to accomplish this is to define a variable as mentioned above.
 | 
					 | 
				
			||||||
In your application this will be set to afero.NewOsFs() during testing you
 | 
					 | 
				
			||||||
can set it to afero.NewMemMapFs().
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
It wouldn't be uncommon to have each test initialize a blank slate memory
 | 
					 | 
				
			||||||
backend. To do this I would define my `appFS = afero.NewOsFs()` somewhere
 | 
					 | 
				
			||||||
appropriate in my application code. This approach ensures that Tests are order
 | 
					 | 
				
			||||||
independent, with no test relying on the state left by an earlier test.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Then in my tests I would initialize a new MemMapFs for each test:
 | 
					 | 
				
			||||||
```go
 | 
					 | 
				
			||||||
func TestExist(t *testing.T) {
 | 
					 | 
				
			||||||
	appFS := afero.NewMemMapFs()
 | 
					 | 
				
			||||||
	// create test files and directories
 | 
					 | 
				
			||||||
	appFS.MkdirAll("src/a", 0755)
 | 
					 | 
				
			||||||
	afero.WriteFile(appFS, "src/a/b", []byte("file b"), 0644)
 | 
					 | 
				
			||||||
	afero.WriteFile(appFS, "src/c", []byte("file c"), 0644)
 | 
					 | 
				
			||||||
	name := "src/c"
 | 
					 | 
				
			||||||
	_, err := appFS.Stat(name)
 | 
					 | 
				
			||||||
	if os.IsNotExist(err) {
 | 
					 | 
				
			||||||
		t.Errorf("file \"%s\" does not exist.\n", name)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
```
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Available Backends
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
## Operating System Native
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
### OsFs
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
The first is simply a wrapper around the native OS calls. This makes it
 | 
					 | 
				
			||||||
very easy to use as all of the calls are the same as the existing OS
 | 
					 | 
				
			||||||
calls. It also makes it trivial to have your code use the OS during
 | 
					 | 
				
			||||||
operation and a mock filesystem during testing or as needed.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
```go
 | 
					 | 
				
			||||||
appfs := afero.NewOsFs()
 | 
					 | 
				
			||||||
appfs.MkdirAll("src/a", 0755))
 | 
					 | 
				
			||||||
```
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
## Memory Backed Storage
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
### MemMapFs
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Afero also provides a fully atomic memory backed filesystem perfect for use in
 | 
					 | 
				
			||||||
mocking and to speed up unnecessary disk io when persistence isn’t
 | 
					 | 
				
			||||||
necessary. It is fully concurrent and will work within go routines
 | 
					 | 
				
			||||||
safely.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
```go
 | 
					 | 
				
			||||||
mm := afero.NewMemMapFs()
 | 
					 | 
				
			||||||
mm.MkdirAll("src/a", 0755))
 | 
					 | 
				
			||||||
```
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#### InMemoryFile
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
As part of MemMapFs, Afero also provides an atomic, fully concurrent memory
 | 
					 | 
				
			||||||
backed file implementation. This can be used in other memory backed file
 | 
					 | 
				
			||||||
systems with ease. Plans are to add a radix tree memory stored file
 | 
					 | 
				
			||||||
system using InMemoryFile.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
## Network Interfaces
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
### SftpFs
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Afero has experimental support for secure file transfer protocol (sftp). Which can
 | 
					 | 
				
			||||||
be used to perform file operations over a encrypted channel.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
## Filtering Backends
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
### BasePathFs
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
The BasePathFs restricts all operations to a given path within an Fs.
 | 
					 | 
				
			||||||
The given file name to the operations on this Fs will be prepended with
 | 
					 | 
				
			||||||
the base path before calling the source Fs.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
```go
 | 
					 | 
				
			||||||
bp := afero.NewBasePathFs(afero.NewOsFs(), "/base/path")
 | 
					 | 
				
			||||||
```
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
### ReadOnlyFs
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
A thin wrapper around the source Fs providing a read only view.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
```go
 | 
					 | 
				
			||||||
fs := afero.NewReadOnlyFs(afero.NewOsFs())
 | 
					 | 
				
			||||||
_, err := fs.Create("/file.txt")
 | 
					 | 
				
			||||||
// err = syscall.EPERM
 | 
					 | 
				
			||||||
```
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# RegexpFs
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
A filtered view on file names, any file NOT matching
 | 
					 | 
				
			||||||
the passed regexp will be treated as non-existing.
 | 
					 | 
				
			||||||
Files not matching the regexp provided will not be created.
 | 
					 | 
				
			||||||
Directories are not filtered.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
```go
 | 
					 | 
				
			||||||
fs := afero.NewRegexpFs(afero.NewMemMapFs(), regexp.MustCompile(`\.txt$`))
 | 
					 | 
				
			||||||
_, err := fs.Create("/file.html")
 | 
					 | 
				
			||||||
// err = syscall.ENOENT
 | 
					 | 
				
			||||||
```
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
### HttpFs
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Afero provides an http compatible backend which can wrap any of the existing
 | 
					 | 
				
			||||||
backends.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
The Http package requires a slightly specific version of Open which
 | 
					 | 
				
			||||||
returns an http.File type.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Afero provides an httpFs file system which satisfies this requirement.
 | 
					 | 
				
			||||||
Any Afero FileSystem can be used as an httpFs.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
```go
 | 
					 | 
				
			||||||
httpFs := afero.NewHttpFs(<ExistingFS>)
 | 
					 | 
				
			||||||
fileserver := http.FileServer(httpFs.Dir(<PATH>)))
 | 
					 | 
				
			||||||
http.Handle("/", fileserver)
 | 
					 | 
				
			||||||
```
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
## Composite Backends
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Afero provides the ability have two filesystems (or more) act as a single
 | 
					 | 
				
			||||||
file system.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
### CacheOnReadFs
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
The CacheOnReadFs will lazily make copies of any accessed files from the base
 | 
					 | 
				
			||||||
layer into the overlay. Subsequent reads will be pulled from the overlay
 | 
					 | 
				
			||||||
directly permitting the request is within the cache duration of when it was
 | 
					 | 
				
			||||||
created in the overlay.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
If the base filesystem is writeable, any changes to files will be
 | 
					 | 
				
			||||||
done first to the base, then to the overlay layer. Write calls to open file
 | 
					 | 
				
			||||||
handles like `Write()` or `Truncate()` to the overlay first.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
To writing files to the overlay only, you can use the overlay Fs directly (not
 | 
					 | 
				
			||||||
via the union Fs).
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Cache files in the layer for the given time.Duration, a cache duration of 0
 | 
					 | 
				
			||||||
means "forever" meaning the file will not be re-requested from the base ever.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
A read-only base will make the overlay also read-only but still copy files
 | 
					 | 
				
			||||||
from the base to the overlay when they're not present (or outdated) in the
 | 
					 | 
				
			||||||
caching layer.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
```go
 | 
					 | 
				
			||||||
base := afero.NewOsFs()
 | 
					 | 
				
			||||||
layer := afero.NewMemMapFs()
 | 
					 | 
				
			||||||
ufs := afero.NewCacheOnReadFs(base, layer, 100 * time.Second)
 | 
					 | 
				
			||||||
```
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
### CopyOnWriteFs()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
The CopyOnWriteFs is a read only base file system with a potentially
 | 
					 | 
				
			||||||
writeable layer on top.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Read operations will first look in the overlay and if not found there, will
 | 
					 | 
				
			||||||
serve the file from the base.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Changes to the file system will only be made in the overlay.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Any attempt to modify a file found only in the base will copy the file to the
 | 
					 | 
				
			||||||
overlay layer before modification (including opening a file with a writable
 | 
					 | 
				
			||||||
handle).
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Removing and Renaming files present only in the base layer is not currently
 | 
					 | 
				
			||||||
permitted. If a file is present in the base layer and the overlay, only the
 | 
					 | 
				
			||||||
overlay will be removed/renamed.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
```go
 | 
					 | 
				
			||||||
	base := afero.NewOsFs()
 | 
					 | 
				
			||||||
	roBase := afero.NewReadOnlyFs(base)
 | 
					 | 
				
			||||||
	ufs := afero.NewCopyOnWriteFs(roBase, afero.NewMemMapFs())
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	fh, _ = ufs.Create("/home/test/file2.txt")
 | 
					 | 
				
			||||||
	fh.WriteString("This is a test")
 | 
					 | 
				
			||||||
	fh.Close()
 | 
					 | 
				
			||||||
```
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
In this example all write operations will only occur in memory (MemMapFs)
 | 
					 | 
				
			||||||
leaving the base filesystem (OsFs) untouched.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
## Desired/possible backends
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
The following is a short list of possible backends we hope someone will
 | 
					 | 
				
			||||||
implement:
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
* SSH
 | 
					 | 
				
			||||||
* ZIP
 | 
					 | 
				
			||||||
* TAR
 | 
					 | 
				
			||||||
* S3
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# About the project
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
## What's in the name
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Afero comes from the latin roots Ad-Facere.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
**"Ad"** is a prefix meaning "to".
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
**"Facere"** is a form of the root "faciō" making "make or do".
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
The literal meaning of afero is "to make" or "to do" which seems very fitting
 | 
					 | 
				
			||||||
for a library that allows one to make files and directories and do things with them.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
The English word that shares the same roots as Afero is "affair". Affair shares
 | 
					 | 
				
			||||||
the same concept but as a noun it means "something that is made or done" or "an
 | 
					 | 
				
			||||||
object of a particular type".
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
It's also nice that unlike some of my other libraries (hugo, cobra, viper) it
 | 
					 | 
				
			||||||
Googles very well.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
## Release Notes
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
* **0.10.0** 2015.12.10
 | 
					 | 
				
			||||||
  * Full compatibility with Windows
 | 
					 | 
				
			||||||
  * Introduction of afero utilities
 | 
					 | 
				
			||||||
  * Test suite rewritten to work cross platform
 | 
					 | 
				
			||||||
  * Normalize paths for MemMapFs
 | 
					 | 
				
			||||||
  * Adding Sync to the file interface
 | 
					 | 
				
			||||||
  * **Breaking Change** Walk and ReadDir have changed parameter order
 | 
					 | 
				
			||||||
  * Moving types used by MemMapFs to a subpackage
 | 
					 | 
				
			||||||
  * General bugfixes and improvements
 | 
					 | 
				
			||||||
* **0.9.0** 2015.11.05
 | 
					 | 
				
			||||||
  * New Walk function similar to filepath.Walk
 | 
					 | 
				
			||||||
  * MemMapFs.OpenFile handles O_CREATE, O_APPEND, O_TRUNC
 | 
					 | 
				
			||||||
  * MemMapFs.Remove now really deletes the file
 | 
					 | 
				
			||||||
  * InMemoryFile.Readdir and Readdirnames work correctly
 | 
					 | 
				
			||||||
  * InMemoryFile functions lock it for concurrent access
 | 
					 | 
				
			||||||
  * Test suite improvements
 | 
					 | 
				
			||||||
* **0.8.0** 2014.10.28
 | 
					 | 
				
			||||||
  * First public version
 | 
					 | 
				
			||||||
  * Interfaces feel ready for people to build using
 | 
					 | 
				
			||||||
  * Interfaces satisfy all known uses
 | 
					 | 
				
			||||||
  * MemMapFs passes the majority of the OS test suite
 | 
					 | 
				
			||||||
  * OsFs passes the majority of the OS test suite
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
## Contributing
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
1. Fork it
 | 
					 | 
				
			||||||
2. Create your feature branch (`git checkout -b my-new-feature`)
 | 
					 | 
				
			||||||
3. Commit your changes (`git commit -am 'Add some feature'`)
 | 
					 | 
				
			||||||
4. Push to the branch (`git push origin my-new-feature`)
 | 
					 | 
				
			||||||
5. Create new Pull Request
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
## Contributors
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Names in no particular order:
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
* [spf13](https://github.com/spf13)
 | 
					 | 
				
			||||||
* [jaqx0r](https://github.com/jaqx0r)
 | 
					 | 
				
			||||||
* [mbertschler](https://github.com/mbertschler)
 | 
					 | 
				
			||||||
* [xor-gate](https://github.com/xor-gate)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
## License
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Afero is released under the Apache 2.0 license. See
 | 
					 | 
				
			||||||
[LICENSE.txt](https://github.com/spf13/afero/blob/master/LICENSE.txt)
 | 
					 | 
				
			||||||
							
								
								
									
										108
									
								
								vendor/github.com/spf13/afero/afero.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										108
									
								
								vendor/github.com/spf13/afero/afero.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,108 +0,0 @@
 | 
				
			|||||||
// Copyright © 2014 Steve Francia <spf@spf13.com>.
 | 
					 | 
				
			||||||
// Copyright 2013 tsuru authors. All rights reserved.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
// 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.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Package afero provides types and methods for interacting with the filesystem,
 | 
					 | 
				
			||||||
// as an abstraction layer.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Afero also provides a few implementations that are mostly interoperable. One that
 | 
					 | 
				
			||||||
// uses the operating system filesystem, one that uses memory to store files
 | 
					 | 
				
			||||||
// (cross platform) and an interface that should be implemented if you want to
 | 
					 | 
				
			||||||
// provide your own filesystem.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
package afero
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"errors"
 | 
					 | 
				
			||||||
	"io"
 | 
					 | 
				
			||||||
	"os"
 | 
					 | 
				
			||||||
	"time"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type Afero struct {
 | 
					 | 
				
			||||||
	Fs
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// File represents a file in the filesystem.
 | 
					 | 
				
			||||||
type File interface {
 | 
					 | 
				
			||||||
	io.Closer
 | 
					 | 
				
			||||||
	io.Reader
 | 
					 | 
				
			||||||
	io.ReaderAt
 | 
					 | 
				
			||||||
	io.Seeker
 | 
					 | 
				
			||||||
	io.Writer
 | 
					 | 
				
			||||||
	io.WriterAt
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	Name() string
 | 
					 | 
				
			||||||
	Readdir(count int) ([]os.FileInfo, error)
 | 
					 | 
				
			||||||
	Readdirnames(n int) ([]string, error)
 | 
					 | 
				
			||||||
	Stat() (os.FileInfo, error)
 | 
					 | 
				
			||||||
	Sync() error
 | 
					 | 
				
			||||||
	Truncate(size int64) error
 | 
					 | 
				
			||||||
	WriteString(s string) (ret int, err error)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Fs is the filesystem interface.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
// Any simulated or real filesystem should implement this interface.
 | 
					 | 
				
			||||||
type Fs interface {
 | 
					 | 
				
			||||||
	// Create creates a file in the filesystem, returning the file and an
 | 
					 | 
				
			||||||
	// error, if any happens.
 | 
					 | 
				
			||||||
	Create(name string) (File, error)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Mkdir creates a directory in the filesystem, return an error if any
 | 
					 | 
				
			||||||
	// happens.
 | 
					 | 
				
			||||||
	Mkdir(name string, perm os.FileMode) error
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// MkdirAll creates a directory path and all parents that does not exist
 | 
					 | 
				
			||||||
	// yet.
 | 
					 | 
				
			||||||
	MkdirAll(path string, perm os.FileMode) error
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Open opens a file, returning it or an error, if any happens.
 | 
					 | 
				
			||||||
	Open(name string) (File, error)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// OpenFile opens a file using the given flags and the given mode.
 | 
					 | 
				
			||||||
	OpenFile(name string, flag int, perm os.FileMode) (File, error)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Remove removes a file identified by name, returning an error, if any
 | 
					 | 
				
			||||||
	// happens.
 | 
					 | 
				
			||||||
	Remove(name string) error
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// RemoveAll removes a directory path and any children it contains. It
 | 
					 | 
				
			||||||
	// does not fail if the path does not exist (return nil).
 | 
					 | 
				
			||||||
	RemoveAll(path string) error
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Rename renames a file.
 | 
					 | 
				
			||||||
	Rename(oldname, newname string) error
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Stat returns a FileInfo describing the named file, or an error, if any
 | 
					 | 
				
			||||||
	// happens.
 | 
					 | 
				
			||||||
	Stat(name string) (os.FileInfo, error)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// The name of this FileSystem
 | 
					 | 
				
			||||||
	Name() string
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	//Chmod changes the mode of the named file to mode.
 | 
					 | 
				
			||||||
	Chmod(name string, mode os.FileMode) error
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	//Chtimes changes the access and modification times of the named file
 | 
					 | 
				
			||||||
	Chtimes(name string, atime time.Time, mtime time.Time) error
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var (
 | 
					 | 
				
			||||||
	ErrFileClosed        = errors.New("File is closed")
 | 
					 | 
				
			||||||
	ErrOutOfRange        = errors.New("Out of range")
 | 
					 | 
				
			||||||
	ErrTooLarge          = errors.New("Too large")
 | 
					 | 
				
			||||||
	ErrFileNotFound      = os.ErrNotExist
 | 
					 | 
				
			||||||
	ErrFileExists        = os.ErrExist
 | 
					 | 
				
			||||||
	ErrDestinationExists = os.ErrExist
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
							
								
								
									
										15
									
								
								vendor/github.com/spf13/afero/appveyor.yml
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										15
									
								
								vendor/github.com/spf13/afero/appveyor.yml
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,15 +0,0 @@
 | 
				
			|||||||
version: '{build}'
 | 
					 | 
				
			||||||
clone_folder: C:\gopath\src\github.com\spf13\afero
 | 
					 | 
				
			||||||
environment:
 | 
					 | 
				
			||||||
  GOPATH: C:\gopath
 | 
					 | 
				
			||||||
build_script:
 | 
					 | 
				
			||||||
- cmd: >-
 | 
					 | 
				
			||||||
    go version
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    go env
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    go get -v github.com/spf13/afero/...
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    go build github.com/spf13/afero
 | 
					 | 
				
			||||||
test_script:
 | 
					 | 
				
			||||||
- cmd: go test -race -v github.com/spf13/afero/...
 | 
					 | 
				
			||||||
							
								
								
									
										180
									
								
								vendor/github.com/spf13/afero/basepath.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										180
									
								
								vendor/github.com/spf13/afero/basepath.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,180 +0,0 @@
 | 
				
			|||||||
package afero
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"os"
 | 
					 | 
				
			||||||
	"path/filepath"
 | 
					 | 
				
			||||||
	"runtime"
 | 
					 | 
				
			||||||
	"strings"
 | 
					 | 
				
			||||||
	"time"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var _ Lstater = (*BasePathFs)(nil)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// The BasePathFs restricts all operations to a given path within an Fs.
 | 
					 | 
				
			||||||
// The given file name to the operations on this Fs will be prepended with
 | 
					 | 
				
			||||||
// the base path before calling the base Fs.
 | 
					 | 
				
			||||||
// Any file name (after filepath.Clean()) outside this base path will be
 | 
					 | 
				
			||||||
// treated as non existing file.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
// Note that it does not clean the error messages on return, so you may
 | 
					 | 
				
			||||||
// reveal the real path on errors.
 | 
					 | 
				
			||||||
type BasePathFs struct {
 | 
					 | 
				
			||||||
	source Fs
 | 
					 | 
				
			||||||
	path   string
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type BasePathFile struct {
 | 
					 | 
				
			||||||
	File
 | 
					 | 
				
			||||||
	path string
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (f *BasePathFile) Name() string {
 | 
					 | 
				
			||||||
	sourcename := f.File.Name()
 | 
					 | 
				
			||||||
	return strings.TrimPrefix(sourcename, filepath.Clean(f.path))
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func NewBasePathFs(source Fs, path string) Fs {
 | 
					 | 
				
			||||||
	return &BasePathFs{source: source, path: path}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// on a file outside the base path it returns the given file name and an error,
 | 
					 | 
				
			||||||
// else the given file with the base path prepended
 | 
					 | 
				
			||||||
func (b *BasePathFs) RealPath(name string) (path string, err error) {
 | 
					 | 
				
			||||||
	if err := validateBasePathName(name); err != nil {
 | 
					 | 
				
			||||||
		return name, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	bpath := filepath.Clean(b.path)
 | 
					 | 
				
			||||||
	path = filepath.Clean(filepath.Join(bpath, name))
 | 
					 | 
				
			||||||
	if !strings.HasPrefix(path, bpath) {
 | 
					 | 
				
			||||||
		return name, os.ErrNotExist
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return path, nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func validateBasePathName(name string) error {
 | 
					 | 
				
			||||||
	if runtime.GOOS != "windows" {
 | 
					 | 
				
			||||||
		// Not much to do here;
 | 
					 | 
				
			||||||
		// the virtual file paths all look absolute on *nix.
 | 
					 | 
				
			||||||
		return nil
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// On Windows a common mistake would be to provide an absolute OS path
 | 
					 | 
				
			||||||
	// We could strip out the base part, but that would not be very portable.
 | 
					 | 
				
			||||||
	if filepath.IsAbs(name) {
 | 
					 | 
				
			||||||
		return os.ErrNotExist
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (b *BasePathFs) Chtimes(name string, atime, mtime time.Time) (err error) {
 | 
					 | 
				
			||||||
	if name, err = b.RealPath(name); err != nil {
 | 
					 | 
				
			||||||
		return &os.PathError{Op: "chtimes", Path: name, Err: err}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return b.source.Chtimes(name, atime, mtime)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (b *BasePathFs) Chmod(name string, mode os.FileMode) (err error) {
 | 
					 | 
				
			||||||
	if name, err = b.RealPath(name); err != nil {
 | 
					 | 
				
			||||||
		return &os.PathError{Op: "chmod", Path: name, Err: err}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return b.source.Chmod(name, mode)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (b *BasePathFs) Name() string {
 | 
					 | 
				
			||||||
	return "BasePathFs"
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (b *BasePathFs) Stat(name string) (fi os.FileInfo, err error) {
 | 
					 | 
				
			||||||
	if name, err = b.RealPath(name); err != nil {
 | 
					 | 
				
			||||||
		return nil, &os.PathError{Op: "stat", Path: name, Err: err}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return b.source.Stat(name)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (b *BasePathFs) Rename(oldname, newname string) (err error) {
 | 
					 | 
				
			||||||
	if oldname, err = b.RealPath(oldname); err != nil {
 | 
					 | 
				
			||||||
		return &os.PathError{Op: "rename", Path: oldname, Err: err}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if newname, err = b.RealPath(newname); err != nil {
 | 
					 | 
				
			||||||
		return &os.PathError{Op: "rename", Path: newname, Err: err}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return b.source.Rename(oldname, newname)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (b *BasePathFs) RemoveAll(name string) (err error) {
 | 
					 | 
				
			||||||
	if name, err = b.RealPath(name); err != nil {
 | 
					 | 
				
			||||||
		return &os.PathError{Op: "remove_all", Path: name, Err: err}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return b.source.RemoveAll(name)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (b *BasePathFs) Remove(name string) (err error) {
 | 
					 | 
				
			||||||
	if name, err = b.RealPath(name); err != nil {
 | 
					 | 
				
			||||||
		return &os.PathError{Op: "remove", Path: name, Err: err}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return b.source.Remove(name)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (b *BasePathFs) OpenFile(name string, flag int, mode os.FileMode) (f File, err error) {
 | 
					 | 
				
			||||||
	if name, err = b.RealPath(name); err != nil {
 | 
					 | 
				
			||||||
		return nil, &os.PathError{Op: "openfile", Path: name, Err: err}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	sourcef, err := b.source.OpenFile(name, flag, mode)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return nil, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return &BasePathFile{sourcef, b.path}, nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (b *BasePathFs) Open(name string) (f File, err error) {
 | 
					 | 
				
			||||||
	if name, err = b.RealPath(name); err != nil {
 | 
					 | 
				
			||||||
		return nil, &os.PathError{Op: "open", Path: name, Err: err}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	sourcef, err := b.source.Open(name)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return nil, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return &BasePathFile{File: sourcef, path: b.path}, nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (b *BasePathFs) Mkdir(name string, mode os.FileMode) (err error) {
 | 
					 | 
				
			||||||
	if name, err = b.RealPath(name); err != nil {
 | 
					 | 
				
			||||||
		return &os.PathError{Op: "mkdir", Path: name, Err: err}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return b.source.Mkdir(name, mode)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (b *BasePathFs) MkdirAll(name string, mode os.FileMode) (err error) {
 | 
					 | 
				
			||||||
	if name, err = b.RealPath(name); err != nil {
 | 
					 | 
				
			||||||
		return &os.PathError{Op: "mkdir", Path: name, Err: err}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return b.source.MkdirAll(name, mode)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (b *BasePathFs) Create(name string) (f File, err error) {
 | 
					 | 
				
			||||||
	if name, err = b.RealPath(name); err != nil {
 | 
					 | 
				
			||||||
		return nil, &os.PathError{Op: "create", Path: name, Err: err}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	sourcef, err := b.source.Create(name)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return nil, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return &BasePathFile{File: sourcef, path: b.path}, nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (b *BasePathFs) LstatIfPossible(name string) (os.FileInfo, bool, error) {
 | 
					 | 
				
			||||||
	name, err := b.RealPath(name)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return nil, false, &os.PathError{Op: "lstat", Path: name, Err: err}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if lstater, ok := b.source.(Lstater); ok {
 | 
					 | 
				
			||||||
		return lstater.LstatIfPossible(name)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	fi, err := b.source.Stat(name)
 | 
					 | 
				
			||||||
	return fi, false, err
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// vim: ts=4 sw=4 noexpandtab nolist syn=go
 | 
					 | 
				
			||||||
							
								
								
									
										290
									
								
								vendor/github.com/spf13/afero/cacheOnReadFs.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										290
									
								
								vendor/github.com/spf13/afero/cacheOnReadFs.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,290 +0,0 @@
 | 
				
			|||||||
package afero
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"os"
 | 
					 | 
				
			||||||
	"syscall"
 | 
					 | 
				
			||||||
	"time"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// If the cache duration is 0, cache time will be unlimited, i.e. once
 | 
					 | 
				
			||||||
// a file is in the layer, the base will never be read again for this file.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
// For cache times greater than 0, the modification time of a file is
 | 
					 | 
				
			||||||
// checked. Note that a lot of file system implementations only allow a
 | 
					 | 
				
			||||||
// resolution of a second for timestamps... or as the godoc for os.Chtimes()
 | 
					 | 
				
			||||||
// states: "The underlying filesystem may truncate or round the values to a
 | 
					 | 
				
			||||||
// less precise time unit."
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
// This caching union will forward all write calls also to the base file
 | 
					 | 
				
			||||||
// system first. To prevent writing to the base Fs, wrap it in a read-only
 | 
					 | 
				
			||||||
// filter - Note: this will also make the overlay read-only, for writing files
 | 
					 | 
				
			||||||
// in the overlay, use the overlay Fs directly, not via the union Fs.
 | 
					 | 
				
			||||||
type CacheOnReadFs struct {
 | 
					 | 
				
			||||||
	base      Fs
 | 
					 | 
				
			||||||
	layer     Fs
 | 
					 | 
				
			||||||
	cacheTime time.Duration
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func NewCacheOnReadFs(base Fs, layer Fs, cacheTime time.Duration) Fs {
 | 
					 | 
				
			||||||
	return &CacheOnReadFs{base: base, layer: layer, cacheTime: cacheTime}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type cacheState int
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const (
 | 
					 | 
				
			||||||
	// not present in the overlay, unknown if it exists in the base:
 | 
					 | 
				
			||||||
	cacheMiss cacheState = iota
 | 
					 | 
				
			||||||
	// present in the overlay and in base, base file is newer:
 | 
					 | 
				
			||||||
	cacheStale
 | 
					 | 
				
			||||||
	// present in the overlay - with cache time == 0 it may exist in the base,
 | 
					 | 
				
			||||||
	// with cacheTime > 0 it exists in the base and is same age or newer in the
 | 
					 | 
				
			||||||
	// overlay
 | 
					 | 
				
			||||||
	cacheHit
 | 
					 | 
				
			||||||
	// happens if someone writes directly to the overlay without
 | 
					 | 
				
			||||||
	// going through this union
 | 
					 | 
				
			||||||
	cacheLocal
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (u *CacheOnReadFs) cacheStatus(name string) (state cacheState, fi os.FileInfo, err error) {
 | 
					 | 
				
			||||||
	var lfi, bfi os.FileInfo
 | 
					 | 
				
			||||||
	lfi, err = u.layer.Stat(name)
 | 
					 | 
				
			||||||
	if err == nil {
 | 
					 | 
				
			||||||
		if u.cacheTime == 0 {
 | 
					 | 
				
			||||||
			return cacheHit, lfi, nil
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if lfi.ModTime().Add(u.cacheTime).Before(time.Now()) {
 | 
					 | 
				
			||||||
			bfi, err = u.base.Stat(name)
 | 
					 | 
				
			||||||
			if err != nil {
 | 
					 | 
				
			||||||
				return cacheLocal, lfi, nil
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			if bfi.ModTime().After(lfi.ModTime()) {
 | 
					 | 
				
			||||||
				return cacheStale, bfi, nil
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		return cacheHit, lfi, nil
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if err == syscall.ENOENT || os.IsNotExist(err) {
 | 
					 | 
				
			||||||
		return cacheMiss, nil, nil
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return cacheMiss, nil, err
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (u *CacheOnReadFs) copyToLayer(name string) error {
 | 
					 | 
				
			||||||
	return copyToLayer(u.base, u.layer, name)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (u *CacheOnReadFs) Chtimes(name string, atime, mtime time.Time) error {
 | 
					 | 
				
			||||||
	st, _, err := u.cacheStatus(name)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	switch st {
 | 
					 | 
				
			||||||
	case cacheLocal:
 | 
					 | 
				
			||||||
	case cacheHit:
 | 
					 | 
				
			||||||
		err = u.base.Chtimes(name, atime, mtime)
 | 
					 | 
				
			||||||
	case cacheStale, cacheMiss:
 | 
					 | 
				
			||||||
		if err := u.copyToLayer(name); err != nil {
 | 
					 | 
				
			||||||
			return err
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		err = u.base.Chtimes(name, atime, mtime)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return u.layer.Chtimes(name, atime, mtime)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (u *CacheOnReadFs) Chmod(name string, mode os.FileMode) error {
 | 
					 | 
				
			||||||
	st, _, err := u.cacheStatus(name)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	switch st {
 | 
					 | 
				
			||||||
	case cacheLocal:
 | 
					 | 
				
			||||||
	case cacheHit:
 | 
					 | 
				
			||||||
		err = u.base.Chmod(name, mode)
 | 
					 | 
				
			||||||
	case cacheStale, cacheMiss:
 | 
					 | 
				
			||||||
		if err := u.copyToLayer(name); err != nil {
 | 
					 | 
				
			||||||
			return err
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		err = u.base.Chmod(name, mode)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return u.layer.Chmod(name, mode)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (u *CacheOnReadFs) Stat(name string) (os.FileInfo, error) {
 | 
					 | 
				
			||||||
	st, fi, err := u.cacheStatus(name)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return nil, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	switch st {
 | 
					 | 
				
			||||||
	case cacheMiss:
 | 
					 | 
				
			||||||
		return u.base.Stat(name)
 | 
					 | 
				
			||||||
	default: // cacheStale has base, cacheHit and cacheLocal the layer os.FileInfo
 | 
					 | 
				
			||||||
		return fi, nil
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (u *CacheOnReadFs) Rename(oldname, newname string) error {
 | 
					 | 
				
			||||||
	st, _, err := u.cacheStatus(oldname)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	switch st {
 | 
					 | 
				
			||||||
	case cacheLocal:
 | 
					 | 
				
			||||||
	case cacheHit:
 | 
					 | 
				
			||||||
		err = u.base.Rename(oldname, newname)
 | 
					 | 
				
			||||||
	case cacheStale, cacheMiss:
 | 
					 | 
				
			||||||
		if err := u.copyToLayer(oldname); err != nil {
 | 
					 | 
				
			||||||
			return err
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		err = u.base.Rename(oldname, newname)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return u.layer.Rename(oldname, newname)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (u *CacheOnReadFs) Remove(name string) error {
 | 
					 | 
				
			||||||
	st, _, err := u.cacheStatus(name)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	switch st {
 | 
					 | 
				
			||||||
	case cacheLocal:
 | 
					 | 
				
			||||||
	case cacheHit, cacheStale, cacheMiss:
 | 
					 | 
				
			||||||
		err = u.base.Remove(name)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return u.layer.Remove(name)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (u *CacheOnReadFs) RemoveAll(name string) error {
 | 
					 | 
				
			||||||
	st, _, err := u.cacheStatus(name)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	switch st {
 | 
					 | 
				
			||||||
	case cacheLocal:
 | 
					 | 
				
			||||||
	case cacheHit, cacheStale, cacheMiss:
 | 
					 | 
				
			||||||
		err = u.base.RemoveAll(name)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return u.layer.RemoveAll(name)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (u *CacheOnReadFs) OpenFile(name string, flag int, perm os.FileMode) (File, error) {
 | 
					 | 
				
			||||||
	st, _, err := u.cacheStatus(name)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return nil, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	switch st {
 | 
					 | 
				
			||||||
	case cacheLocal, cacheHit:
 | 
					 | 
				
			||||||
	default:
 | 
					 | 
				
			||||||
		if err := u.copyToLayer(name); err != nil {
 | 
					 | 
				
			||||||
			return nil, err
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if flag&(os.O_WRONLY|syscall.O_RDWR|os.O_APPEND|os.O_CREATE|os.O_TRUNC) != 0 {
 | 
					 | 
				
			||||||
		bfi, err := u.base.OpenFile(name, flag, perm)
 | 
					 | 
				
			||||||
		if err != nil {
 | 
					 | 
				
			||||||
			return nil, err
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		lfi, err := u.layer.OpenFile(name, flag, perm)
 | 
					 | 
				
			||||||
		if err != nil {
 | 
					 | 
				
			||||||
			bfi.Close() // oops, what if O_TRUNC was set and file opening in the layer failed...?
 | 
					 | 
				
			||||||
			return nil, err
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		return &UnionFile{Base: bfi, Layer: lfi}, nil
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return u.layer.OpenFile(name, flag, perm)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (u *CacheOnReadFs) Open(name string) (File, error) {
 | 
					 | 
				
			||||||
	st, fi, err := u.cacheStatus(name)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return nil, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	switch st {
 | 
					 | 
				
			||||||
	case cacheLocal:
 | 
					 | 
				
			||||||
		return u.layer.Open(name)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	case cacheMiss:
 | 
					 | 
				
			||||||
		bfi, err := u.base.Stat(name)
 | 
					 | 
				
			||||||
		if err != nil {
 | 
					 | 
				
			||||||
			return nil, err
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if bfi.IsDir() {
 | 
					 | 
				
			||||||
			return u.base.Open(name)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if err := u.copyToLayer(name); err != nil {
 | 
					 | 
				
			||||||
			return nil, err
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		return u.layer.Open(name)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	case cacheStale:
 | 
					 | 
				
			||||||
		if !fi.IsDir() {
 | 
					 | 
				
			||||||
			if err := u.copyToLayer(name); err != nil {
 | 
					 | 
				
			||||||
				return nil, err
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			return u.layer.Open(name)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	case cacheHit:
 | 
					 | 
				
			||||||
		if !fi.IsDir() {
 | 
					 | 
				
			||||||
			return u.layer.Open(name)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	// the dirs from cacheHit, cacheStale fall down here:
 | 
					 | 
				
			||||||
	bfile, _ := u.base.Open(name)
 | 
					 | 
				
			||||||
	lfile, err := u.layer.Open(name)
 | 
					 | 
				
			||||||
	if err != nil && bfile == nil {
 | 
					 | 
				
			||||||
		return nil, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return &UnionFile{Base: bfile, Layer: lfile}, nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (u *CacheOnReadFs) Mkdir(name string, perm os.FileMode) error {
 | 
					 | 
				
			||||||
	err := u.base.Mkdir(name, perm)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return u.layer.MkdirAll(name, perm) // yes, MkdirAll... we cannot assume it exists in the cache
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (u *CacheOnReadFs) Name() string {
 | 
					 | 
				
			||||||
	return "CacheOnReadFs"
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (u *CacheOnReadFs) MkdirAll(name string, perm os.FileMode) error {
 | 
					 | 
				
			||||||
	err := u.base.MkdirAll(name, perm)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return u.layer.MkdirAll(name, perm)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (u *CacheOnReadFs) Create(name string) (File, error) {
 | 
					 | 
				
			||||||
	bfh, err := u.base.Create(name)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return nil, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	lfh, err := u.layer.Create(name)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		// oops, see comment about OS_TRUNC above, should we remove? then we have to
 | 
					 | 
				
			||||||
		// remember if the file did not exist before
 | 
					 | 
				
			||||||
		bfh.Close()
 | 
					 | 
				
			||||||
		return nil, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return &UnionFile{Base: bfh, Layer: lfh}, nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										22
									
								
								vendor/github.com/spf13/afero/const_bsds.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										22
									
								
								vendor/github.com/spf13/afero/const_bsds.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,22 +0,0 @@
 | 
				
			|||||||
// Copyright © 2016 Steve Francia <spf@spf13.com>.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
// 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.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// +build darwin openbsd freebsd netbsd dragonfly
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
package afero
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"syscall"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const BADFD = syscall.EBADF
 | 
					 | 
				
			||||||
							
								
								
									
										25
									
								
								vendor/github.com/spf13/afero/const_win_unix.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										25
									
								
								vendor/github.com/spf13/afero/const_win_unix.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,25 +0,0 @@
 | 
				
			|||||||
// Copyright © 2016 Steve Francia <spf@spf13.com>.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
// 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.
 | 
					 | 
				
			||||||
// +build !darwin
 | 
					 | 
				
			||||||
// +build !openbsd
 | 
					 | 
				
			||||||
// +build !freebsd
 | 
					 | 
				
			||||||
// +build !dragonfly
 | 
					 | 
				
			||||||
// +build !netbsd
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
package afero
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"syscall"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const BADFD = syscall.EBADFD
 | 
					 | 
				
			||||||
							
								
								
									
										293
									
								
								vendor/github.com/spf13/afero/copyOnWriteFs.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										293
									
								
								vendor/github.com/spf13/afero/copyOnWriteFs.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,293 +0,0 @@
 | 
				
			|||||||
package afero
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"fmt"
 | 
					 | 
				
			||||||
	"os"
 | 
					 | 
				
			||||||
	"path/filepath"
 | 
					 | 
				
			||||||
	"syscall"
 | 
					 | 
				
			||||||
	"time"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var _ Lstater = (*CopyOnWriteFs)(nil)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// The CopyOnWriteFs is a union filesystem: a read only base file system with
 | 
					 | 
				
			||||||
// a possibly writeable layer on top. Changes to the file system will only
 | 
					 | 
				
			||||||
// be made in the overlay: Changing an existing file in the base layer which
 | 
					 | 
				
			||||||
// is not present in the overlay will copy the file to the overlay ("changing"
 | 
					 | 
				
			||||||
// includes also calls to e.g. Chtimes() and Chmod()).
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
// Reading directories is currently only supported via Open(), not OpenFile().
 | 
					 | 
				
			||||||
type CopyOnWriteFs struct {
 | 
					 | 
				
			||||||
	base  Fs
 | 
					 | 
				
			||||||
	layer Fs
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func NewCopyOnWriteFs(base Fs, layer Fs) Fs {
 | 
					 | 
				
			||||||
	return &CopyOnWriteFs{base: base, layer: layer}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Returns true if the file is not in the overlay
 | 
					 | 
				
			||||||
func (u *CopyOnWriteFs) isBaseFile(name string) (bool, error) {
 | 
					 | 
				
			||||||
	if _, err := u.layer.Stat(name); err == nil {
 | 
					 | 
				
			||||||
		return false, nil
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	_, err := u.base.Stat(name)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		if oerr, ok := err.(*os.PathError); ok {
 | 
					 | 
				
			||||||
			if oerr.Err == os.ErrNotExist || oerr.Err == syscall.ENOENT || oerr.Err == syscall.ENOTDIR {
 | 
					 | 
				
			||||||
				return false, nil
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if err == syscall.ENOENT {
 | 
					 | 
				
			||||||
			return false, nil
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return true, err
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (u *CopyOnWriteFs) copyToLayer(name string) error {
 | 
					 | 
				
			||||||
	return copyToLayer(u.base, u.layer, name)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (u *CopyOnWriteFs) Chtimes(name string, atime, mtime time.Time) error {
 | 
					 | 
				
			||||||
	b, err := u.isBaseFile(name)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if b {
 | 
					 | 
				
			||||||
		if err := u.copyToLayer(name); err != nil {
 | 
					 | 
				
			||||||
			return err
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return u.layer.Chtimes(name, atime, mtime)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (u *CopyOnWriteFs) Chmod(name string, mode os.FileMode) error {
 | 
					 | 
				
			||||||
	b, err := u.isBaseFile(name)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if b {
 | 
					 | 
				
			||||||
		if err := u.copyToLayer(name); err != nil {
 | 
					 | 
				
			||||||
			return err
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return u.layer.Chmod(name, mode)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (u *CopyOnWriteFs) Stat(name string) (os.FileInfo, error) {
 | 
					 | 
				
			||||||
	fi, err := u.layer.Stat(name)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		isNotExist := u.isNotExist(err)
 | 
					 | 
				
			||||||
		if isNotExist {
 | 
					 | 
				
			||||||
			return u.base.Stat(name)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		return nil, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return fi, nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (u *CopyOnWriteFs) LstatIfPossible(name string) (os.FileInfo, bool, error) {
 | 
					 | 
				
			||||||
	llayer, ok1 := u.layer.(Lstater)
 | 
					 | 
				
			||||||
	lbase, ok2 := u.base.(Lstater)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if ok1 {
 | 
					 | 
				
			||||||
		fi, b, err := llayer.LstatIfPossible(name)
 | 
					 | 
				
			||||||
		if err == nil {
 | 
					 | 
				
			||||||
			return fi, b, nil
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if !u.isNotExist(err) {
 | 
					 | 
				
			||||||
			return nil, b, err
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if ok2 {
 | 
					 | 
				
			||||||
		fi, b, err := lbase.LstatIfPossible(name)
 | 
					 | 
				
			||||||
		if err == nil {
 | 
					 | 
				
			||||||
			return fi, b, nil
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if !u.isNotExist(err) {
 | 
					 | 
				
			||||||
			return nil, b, err
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	fi, err := u.Stat(name)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return fi, false, err
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (u *CopyOnWriteFs) isNotExist(err error) bool {
 | 
					 | 
				
			||||||
	if e, ok := err.(*os.PathError); ok {
 | 
					 | 
				
			||||||
		err = e.Err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if err == os.ErrNotExist || err == syscall.ENOENT || err == syscall.ENOTDIR {
 | 
					 | 
				
			||||||
		return true
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return false
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Renaming files present only in the base layer is not permitted
 | 
					 | 
				
			||||||
func (u *CopyOnWriteFs) Rename(oldname, newname string) error {
 | 
					 | 
				
			||||||
	b, err := u.isBaseFile(oldname)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if b {
 | 
					 | 
				
			||||||
		return syscall.EPERM
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return u.layer.Rename(oldname, newname)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Removing files present only in the base layer is not permitted. If
 | 
					 | 
				
			||||||
// a file is present in the base layer and the overlay, only the overlay
 | 
					 | 
				
			||||||
// will be removed.
 | 
					 | 
				
			||||||
func (u *CopyOnWriteFs) Remove(name string) error {
 | 
					 | 
				
			||||||
	err := u.layer.Remove(name)
 | 
					 | 
				
			||||||
	switch err {
 | 
					 | 
				
			||||||
	case syscall.ENOENT:
 | 
					 | 
				
			||||||
		_, err = u.base.Stat(name)
 | 
					 | 
				
			||||||
		if err == nil {
 | 
					 | 
				
			||||||
			return syscall.EPERM
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		return syscall.ENOENT
 | 
					 | 
				
			||||||
	default:
 | 
					 | 
				
			||||||
		return err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (u *CopyOnWriteFs) RemoveAll(name string) error {
 | 
					 | 
				
			||||||
	err := u.layer.RemoveAll(name)
 | 
					 | 
				
			||||||
	switch err {
 | 
					 | 
				
			||||||
	case syscall.ENOENT:
 | 
					 | 
				
			||||||
		_, err = u.base.Stat(name)
 | 
					 | 
				
			||||||
		if err == nil {
 | 
					 | 
				
			||||||
			return syscall.EPERM
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		return syscall.ENOENT
 | 
					 | 
				
			||||||
	default:
 | 
					 | 
				
			||||||
		return err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (u *CopyOnWriteFs) OpenFile(name string, flag int, perm os.FileMode) (File, error) {
 | 
					 | 
				
			||||||
	b, err := u.isBaseFile(name)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return nil, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if flag&(os.O_WRONLY|os.O_RDWR|os.O_APPEND|os.O_CREATE|os.O_TRUNC) != 0 {
 | 
					 | 
				
			||||||
		if b {
 | 
					 | 
				
			||||||
			if err = u.copyToLayer(name); err != nil {
 | 
					 | 
				
			||||||
				return nil, err
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			return u.layer.OpenFile(name, flag, perm)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		dir := filepath.Dir(name)
 | 
					 | 
				
			||||||
		isaDir, err := IsDir(u.base, dir)
 | 
					 | 
				
			||||||
		if err != nil && !os.IsNotExist(err) {
 | 
					 | 
				
			||||||
			return nil, err
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if isaDir {
 | 
					 | 
				
			||||||
			if err = u.layer.MkdirAll(dir, 0777); err != nil {
 | 
					 | 
				
			||||||
				return nil, err
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			return u.layer.OpenFile(name, flag, perm)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		isaDir, err = IsDir(u.layer, dir)
 | 
					 | 
				
			||||||
		if err != nil {
 | 
					 | 
				
			||||||
			return nil, err
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if isaDir {
 | 
					 | 
				
			||||||
			return u.layer.OpenFile(name, flag, perm)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		return nil, &os.PathError{Op: "open", Path: name, Err: syscall.ENOTDIR} // ...or os.ErrNotExist?
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if b {
 | 
					 | 
				
			||||||
		return u.base.OpenFile(name, flag, perm)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return u.layer.OpenFile(name, flag, perm)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// This function handles the 9 different possibilities caused
 | 
					 | 
				
			||||||
// by the union which are the intersection of the following...
 | 
					 | 
				
			||||||
//  layer: doesn't exist, exists as a file, and exists as a directory
 | 
					 | 
				
			||||||
//  base:  doesn't exist, exists as a file, and exists as a directory
 | 
					 | 
				
			||||||
func (u *CopyOnWriteFs) Open(name string) (File, error) {
 | 
					 | 
				
			||||||
	// Since the overlay overrides the base we check that first
 | 
					 | 
				
			||||||
	b, err := u.isBaseFile(name)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return nil, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// If overlay doesn't exist, return the base (base state irrelevant)
 | 
					 | 
				
			||||||
	if b {
 | 
					 | 
				
			||||||
		return u.base.Open(name)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// If overlay is a file, return it (base state irrelevant)
 | 
					 | 
				
			||||||
	dir, err := IsDir(u.layer, name)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return nil, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if !dir {
 | 
					 | 
				
			||||||
		return u.layer.Open(name)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Overlay is a directory, base state now matters.
 | 
					 | 
				
			||||||
	// Base state has 3 states to check but 2 outcomes:
 | 
					 | 
				
			||||||
	// A. It's a file or non-readable in the base (return just the overlay)
 | 
					 | 
				
			||||||
	// B. It's an accessible directory in the base (return a UnionFile)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// If base is file or nonreadable, return overlay
 | 
					 | 
				
			||||||
	dir, err = IsDir(u.base, name)
 | 
					 | 
				
			||||||
	if !dir || err != nil {
 | 
					 | 
				
			||||||
		return u.layer.Open(name)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Both base & layer are directories
 | 
					 | 
				
			||||||
	// Return union file (if opens are without error)
 | 
					 | 
				
			||||||
	bfile, bErr := u.base.Open(name)
 | 
					 | 
				
			||||||
	lfile, lErr := u.layer.Open(name)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// If either have errors at this point something is very wrong. Return nil and the errors
 | 
					 | 
				
			||||||
	if bErr != nil || lErr != nil {
 | 
					 | 
				
			||||||
		return nil, fmt.Errorf("BaseErr: %v\nOverlayErr: %v", bErr, lErr)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return &UnionFile{Base: bfile, Layer: lfile}, nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (u *CopyOnWriteFs) Mkdir(name string, perm os.FileMode) error {
 | 
					 | 
				
			||||||
	dir, err := IsDir(u.base, name)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return u.layer.MkdirAll(name, perm)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if dir {
 | 
					 | 
				
			||||||
		return ErrFileExists
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return u.layer.MkdirAll(name, perm)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (u *CopyOnWriteFs) Name() string {
 | 
					 | 
				
			||||||
	return "CopyOnWriteFs"
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (u *CopyOnWriteFs) MkdirAll(name string, perm os.FileMode) error {
 | 
					 | 
				
			||||||
	dir, err := IsDir(u.base, name)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return u.layer.MkdirAll(name, perm)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if dir {
 | 
					 | 
				
			||||||
		// This is in line with how os.MkdirAll behaves.
 | 
					 | 
				
			||||||
		return nil
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return u.layer.MkdirAll(name, perm)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (u *CopyOnWriteFs) Create(name string) (File, error) {
 | 
					 | 
				
			||||||
	return u.OpenFile(name, os.O_CREATE|os.O_TRUNC|os.O_RDWR, 0666)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										3
									
								
								vendor/github.com/spf13/afero/go.mod
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								vendor/github.com/spf13/afero/go.mod
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,3 +0,0 @@
 | 
				
			|||||||
module github.com/spf13/afero
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
require golang.org/x/text v0.3.0
 | 
					 | 
				
			||||||
							
								
								
									
										2
									
								
								vendor/github.com/spf13/afero/go.sum
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								vendor/github.com/spf13/afero/go.sum
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,2 +0,0 @@
 | 
				
			|||||||
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
 | 
					 | 
				
			||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 | 
					 | 
				
			||||||
							
								
								
									
										110
									
								
								vendor/github.com/spf13/afero/httpFs.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										110
									
								
								vendor/github.com/spf13/afero/httpFs.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,110 +0,0 @@
 | 
				
			|||||||
// Copyright © 2014 Steve Francia <spf@spf13.com>.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
// 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.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
package afero
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"errors"
 | 
					 | 
				
			||||||
	"net/http"
 | 
					 | 
				
			||||||
	"os"
 | 
					 | 
				
			||||||
	"path"
 | 
					 | 
				
			||||||
	"path/filepath"
 | 
					 | 
				
			||||||
	"strings"
 | 
					 | 
				
			||||||
	"time"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type httpDir struct {
 | 
					 | 
				
			||||||
	basePath string
 | 
					 | 
				
			||||||
	fs       HttpFs
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (d httpDir) Open(name string) (http.File, error) {
 | 
					 | 
				
			||||||
	if filepath.Separator != '/' && strings.IndexRune(name, filepath.Separator) >= 0 ||
 | 
					 | 
				
			||||||
		strings.Contains(name, "\x00") {
 | 
					 | 
				
			||||||
		return nil, errors.New("http: invalid character in file path")
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	dir := string(d.basePath)
 | 
					 | 
				
			||||||
	if dir == "" {
 | 
					 | 
				
			||||||
		dir = "."
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	f, err := d.fs.Open(filepath.Join(dir, filepath.FromSlash(path.Clean("/"+name))))
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return nil, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return f, nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type HttpFs struct {
 | 
					 | 
				
			||||||
	source Fs
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func NewHttpFs(source Fs) *HttpFs {
 | 
					 | 
				
			||||||
	return &HttpFs{source: source}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (h HttpFs) Dir(s string) *httpDir {
 | 
					 | 
				
			||||||
	return &httpDir{basePath: s, fs: h}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (h HttpFs) Name() string { return "h HttpFs" }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (h HttpFs) Create(name string) (File, error) {
 | 
					 | 
				
			||||||
	return h.source.Create(name)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (h HttpFs) Chmod(name string, mode os.FileMode) error {
 | 
					 | 
				
			||||||
	return h.source.Chmod(name, mode)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (h HttpFs) Chtimes(name string, atime time.Time, mtime time.Time) error {
 | 
					 | 
				
			||||||
	return h.source.Chtimes(name, atime, mtime)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (h HttpFs) Mkdir(name string, perm os.FileMode) error {
 | 
					 | 
				
			||||||
	return h.source.Mkdir(name, perm)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (h HttpFs) MkdirAll(path string, perm os.FileMode) error {
 | 
					 | 
				
			||||||
	return h.source.MkdirAll(path, perm)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (h HttpFs) Open(name string) (http.File, error) {
 | 
					 | 
				
			||||||
	f, err := h.source.Open(name)
 | 
					 | 
				
			||||||
	if err == nil {
 | 
					 | 
				
			||||||
		if httpfile, ok := f.(http.File); ok {
 | 
					 | 
				
			||||||
			return httpfile, nil
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return nil, err
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (h HttpFs) OpenFile(name string, flag int, perm os.FileMode) (File, error) {
 | 
					 | 
				
			||||||
	return h.source.OpenFile(name, flag, perm)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (h HttpFs) Remove(name string) error {
 | 
					 | 
				
			||||||
	return h.source.Remove(name)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (h HttpFs) RemoveAll(path string) error {
 | 
					 | 
				
			||||||
	return h.source.RemoveAll(path)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (h HttpFs) Rename(oldname, newname string) error {
 | 
					 | 
				
			||||||
	return h.source.Rename(oldname, newname)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (h HttpFs) Stat(name string) (os.FileInfo, error) {
 | 
					 | 
				
			||||||
	return h.source.Stat(name)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										230
									
								
								vendor/github.com/spf13/afero/ioutil.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										230
									
								
								vendor/github.com/spf13/afero/ioutil.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,230 +0,0 @@
 | 
				
			|||||||
// Copyright ©2015 The Go Authors
 | 
					 | 
				
			||||||
// Copyright ©2015 Steve Francia <spf@spf13.com>
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
// 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.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
package afero
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"bytes"
 | 
					 | 
				
			||||||
	"io"
 | 
					 | 
				
			||||||
	"os"
 | 
					 | 
				
			||||||
	"path/filepath"
 | 
					 | 
				
			||||||
	"sort"
 | 
					 | 
				
			||||||
	"strconv"
 | 
					 | 
				
			||||||
	"sync"
 | 
					 | 
				
			||||||
	"time"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// byName implements sort.Interface.
 | 
					 | 
				
			||||||
type byName []os.FileInfo
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (f byName) Len() int           { return len(f) }
 | 
					 | 
				
			||||||
func (f byName) Less(i, j int) bool { return f[i].Name() < f[j].Name() }
 | 
					 | 
				
			||||||
func (f byName) Swap(i, j int)      { f[i], f[j] = f[j], f[i] }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// ReadDir reads the directory named by dirname and returns
 | 
					 | 
				
			||||||
// a list of sorted directory entries.
 | 
					 | 
				
			||||||
func (a Afero) ReadDir(dirname string) ([]os.FileInfo, error) {
 | 
					 | 
				
			||||||
	return ReadDir(a.Fs, dirname)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func ReadDir(fs Fs, dirname string) ([]os.FileInfo, error) {
 | 
					 | 
				
			||||||
	f, err := fs.Open(dirname)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return nil, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	list, err := f.Readdir(-1)
 | 
					 | 
				
			||||||
	f.Close()
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return nil, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	sort.Sort(byName(list))
 | 
					 | 
				
			||||||
	return list, nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// ReadFile reads the file named by filename and returns the contents.
 | 
					 | 
				
			||||||
// A successful call returns err == nil, not err == EOF. Because ReadFile
 | 
					 | 
				
			||||||
// reads the whole file, it does not treat an EOF from Read as an error
 | 
					 | 
				
			||||||
// to be reported.
 | 
					 | 
				
			||||||
func (a Afero) ReadFile(filename string) ([]byte, error) {
 | 
					 | 
				
			||||||
	return ReadFile(a.Fs, filename)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func ReadFile(fs Fs, filename string) ([]byte, error) {
 | 
					 | 
				
			||||||
	f, err := fs.Open(filename)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return nil, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	defer f.Close()
 | 
					 | 
				
			||||||
	// It's a good but not certain bet that FileInfo will tell us exactly how much to
 | 
					 | 
				
			||||||
	// read, so let's try it but be prepared for the answer to be wrong.
 | 
					 | 
				
			||||||
	var n int64
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if fi, err := f.Stat(); err == nil {
 | 
					 | 
				
			||||||
		// Don't preallocate a huge buffer, just in case.
 | 
					 | 
				
			||||||
		if size := fi.Size(); size < 1e9 {
 | 
					 | 
				
			||||||
			n = size
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	// As initial capacity for readAll, use n + a little extra in case Size is zero,
 | 
					 | 
				
			||||||
	// and to avoid another allocation after Read has filled the buffer.  The readAll
 | 
					 | 
				
			||||||
	// call will read into its allocated internal buffer cheaply.  If the size was
 | 
					 | 
				
			||||||
	// wrong, we'll either waste some space off the end or reallocate as needed, but
 | 
					 | 
				
			||||||
	// in the overwhelmingly common case we'll get it just right.
 | 
					 | 
				
			||||||
	return readAll(f, n+bytes.MinRead)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// readAll reads from r until an error or EOF and returns the data it read
 | 
					 | 
				
			||||||
// from the internal buffer allocated with a specified capacity.
 | 
					 | 
				
			||||||
func readAll(r io.Reader, capacity int64) (b []byte, err error) {
 | 
					 | 
				
			||||||
	buf := bytes.NewBuffer(make([]byte, 0, capacity))
 | 
					 | 
				
			||||||
	// If the buffer overflows, we will get bytes.ErrTooLarge.
 | 
					 | 
				
			||||||
	// Return that as an error. Any other panic remains.
 | 
					 | 
				
			||||||
	defer func() {
 | 
					 | 
				
			||||||
		e := recover()
 | 
					 | 
				
			||||||
		if e == nil {
 | 
					 | 
				
			||||||
			return
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if panicErr, ok := e.(error); ok && panicErr == bytes.ErrTooLarge {
 | 
					 | 
				
			||||||
			err = panicErr
 | 
					 | 
				
			||||||
		} else {
 | 
					 | 
				
			||||||
			panic(e)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}()
 | 
					 | 
				
			||||||
	_, err = buf.ReadFrom(r)
 | 
					 | 
				
			||||||
	return buf.Bytes(), err
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// ReadAll reads from r until an error or EOF and returns the data it read.
 | 
					 | 
				
			||||||
// A successful call returns err == nil, not err == EOF. Because ReadAll is
 | 
					 | 
				
			||||||
// defined to read from src until EOF, it does not treat an EOF from Read
 | 
					 | 
				
			||||||
// as an error to be reported.
 | 
					 | 
				
			||||||
func ReadAll(r io.Reader) ([]byte, error) {
 | 
					 | 
				
			||||||
	return readAll(r, bytes.MinRead)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// WriteFile writes data to a file named by filename.
 | 
					 | 
				
			||||||
// If the file does not exist, WriteFile creates it with permissions perm;
 | 
					 | 
				
			||||||
// otherwise WriteFile truncates it before writing.
 | 
					 | 
				
			||||||
func (a Afero) WriteFile(filename string, data []byte, perm os.FileMode) error {
 | 
					 | 
				
			||||||
	return WriteFile(a.Fs, filename, data, perm)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func WriteFile(fs Fs, filename string, data []byte, perm os.FileMode) error {
 | 
					 | 
				
			||||||
	f, err := fs.OpenFile(filename, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, perm)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	n, err := f.Write(data)
 | 
					 | 
				
			||||||
	if err == nil && n < len(data) {
 | 
					 | 
				
			||||||
		err = io.ErrShortWrite
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if err1 := f.Close(); err == nil {
 | 
					 | 
				
			||||||
		err = err1
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return err
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Random number state.
 | 
					 | 
				
			||||||
// We generate random temporary file names so that there's a good
 | 
					 | 
				
			||||||
// chance the file doesn't exist yet - keeps the number of tries in
 | 
					 | 
				
			||||||
// TempFile to a minimum.
 | 
					 | 
				
			||||||
var rand uint32
 | 
					 | 
				
			||||||
var randmu sync.Mutex
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func reseed() uint32 {
 | 
					 | 
				
			||||||
	return uint32(time.Now().UnixNano() + int64(os.Getpid()))
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func nextSuffix() string {
 | 
					 | 
				
			||||||
	randmu.Lock()
 | 
					 | 
				
			||||||
	r := rand
 | 
					 | 
				
			||||||
	if r == 0 {
 | 
					 | 
				
			||||||
		r = reseed()
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	r = r*1664525 + 1013904223 // constants from Numerical Recipes
 | 
					 | 
				
			||||||
	rand = r
 | 
					 | 
				
			||||||
	randmu.Unlock()
 | 
					 | 
				
			||||||
	return strconv.Itoa(int(1e9 + r%1e9))[1:]
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// TempFile creates a new temporary file in the directory dir
 | 
					 | 
				
			||||||
// with a name beginning with prefix, opens the file for reading
 | 
					 | 
				
			||||||
// and writing, and returns the resulting *File.
 | 
					 | 
				
			||||||
// If dir is the empty string, TempFile uses the default directory
 | 
					 | 
				
			||||||
// for temporary files (see os.TempDir).
 | 
					 | 
				
			||||||
// Multiple programs calling TempFile simultaneously
 | 
					 | 
				
			||||||
// will not choose the same file.  The caller can use f.Name()
 | 
					 | 
				
			||||||
// to find the pathname of the file.  It is the caller's responsibility
 | 
					 | 
				
			||||||
// to remove the file when no longer needed.
 | 
					 | 
				
			||||||
func (a Afero) TempFile(dir, prefix string) (f File, err error) {
 | 
					 | 
				
			||||||
	return TempFile(a.Fs, dir, prefix)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func TempFile(fs Fs, dir, prefix string) (f File, err error) {
 | 
					 | 
				
			||||||
	if dir == "" {
 | 
					 | 
				
			||||||
		dir = os.TempDir()
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	nconflict := 0
 | 
					 | 
				
			||||||
	for i := 0; i < 10000; i++ {
 | 
					 | 
				
			||||||
		name := filepath.Join(dir, prefix+nextSuffix())
 | 
					 | 
				
			||||||
		f, err = fs.OpenFile(name, os.O_RDWR|os.O_CREATE|os.O_EXCL, 0600)
 | 
					 | 
				
			||||||
		if os.IsExist(err) {
 | 
					 | 
				
			||||||
			if nconflict++; nconflict > 10 {
 | 
					 | 
				
			||||||
				randmu.Lock()
 | 
					 | 
				
			||||||
				rand = reseed()
 | 
					 | 
				
			||||||
				randmu.Unlock()
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			continue
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		break
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// TempDir creates a new temporary directory in the directory dir
 | 
					 | 
				
			||||||
// with a name beginning with prefix and returns the path of the
 | 
					 | 
				
			||||||
// new directory.  If dir is the empty string, TempDir uses the
 | 
					 | 
				
			||||||
// default directory for temporary files (see os.TempDir).
 | 
					 | 
				
			||||||
// Multiple programs calling TempDir simultaneously
 | 
					 | 
				
			||||||
// will not choose the same directory.  It is the caller's responsibility
 | 
					 | 
				
			||||||
// to remove the directory when no longer needed.
 | 
					 | 
				
			||||||
func (a Afero) TempDir(dir, prefix string) (name string, err error) {
 | 
					 | 
				
			||||||
	return TempDir(a.Fs, dir, prefix)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
func TempDir(fs Fs, dir, prefix string) (name string, err error) {
 | 
					 | 
				
			||||||
	if dir == "" {
 | 
					 | 
				
			||||||
		dir = os.TempDir()
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	nconflict := 0
 | 
					 | 
				
			||||||
	for i := 0; i < 10000; i++ {
 | 
					 | 
				
			||||||
		try := filepath.Join(dir, prefix+nextSuffix())
 | 
					 | 
				
			||||||
		err = fs.Mkdir(try, 0700)
 | 
					 | 
				
			||||||
		if os.IsExist(err) {
 | 
					 | 
				
			||||||
			if nconflict++; nconflict > 10 {
 | 
					 | 
				
			||||||
				randmu.Lock()
 | 
					 | 
				
			||||||
				rand = reseed()
 | 
					 | 
				
			||||||
				randmu.Unlock()
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			continue
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if err == nil {
 | 
					 | 
				
			||||||
			name = try
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		break
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										27
									
								
								vendor/github.com/spf13/afero/lstater.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										27
									
								
								vendor/github.com/spf13/afero/lstater.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,27 +0,0 @@
 | 
				
			|||||||
// Copyright © 2018 Steve Francia <spf@spf13.com>.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
// 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.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
package afero
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"os"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Lstater is an optional interface in Afero. It is only implemented by the
 | 
					 | 
				
			||||||
// filesystems saying so.
 | 
					 | 
				
			||||||
// It will call Lstat if the filesystem iself is, or it delegates to, the os filesystem.
 | 
					 | 
				
			||||||
// Else it will call Stat.
 | 
					 | 
				
			||||||
// In addtion to the FileInfo, it will return a boolean telling whether Lstat was called or not.
 | 
					 | 
				
			||||||
type Lstater interface {
 | 
					 | 
				
			||||||
	LstatIfPossible(name string) (os.FileInfo, bool, error)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										110
									
								
								vendor/github.com/spf13/afero/match.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										110
									
								
								vendor/github.com/spf13/afero/match.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,110 +0,0 @@
 | 
				
			|||||||
// Copyright © 2014 Steve Francia <spf@spf13.com>.
 | 
					 | 
				
			||||||
// Copyright 2009 The Go Authors. All rights reserved.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// 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.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
package afero
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"path/filepath"
 | 
					 | 
				
			||||||
	"sort"
 | 
					 | 
				
			||||||
	"strings"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Glob returns the names of all files matching pattern or nil
 | 
					 | 
				
			||||||
// if there is no matching file. The syntax of patterns is the same
 | 
					 | 
				
			||||||
// as in Match. The pattern may describe hierarchical names such as
 | 
					 | 
				
			||||||
// /usr/*/bin/ed (assuming the Separator is '/').
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
// Glob ignores file system errors such as I/O errors reading directories.
 | 
					 | 
				
			||||||
// The only possible returned error is ErrBadPattern, when pattern
 | 
					 | 
				
			||||||
// is malformed.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
// This was adapted from (http://golang.org/pkg/path/filepath) and uses several
 | 
					 | 
				
			||||||
// built-ins from that package.
 | 
					 | 
				
			||||||
func Glob(fs Fs, pattern string) (matches []string, err error) {
 | 
					 | 
				
			||||||
	if !hasMeta(pattern) {
 | 
					 | 
				
			||||||
		// Lstat not supported by a ll filesystems.
 | 
					 | 
				
			||||||
		if _, err = lstatIfPossible(fs, pattern); err != nil {
 | 
					 | 
				
			||||||
			return nil, nil
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		return []string{pattern}, nil
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	dir, file := filepath.Split(pattern)
 | 
					 | 
				
			||||||
	switch dir {
 | 
					 | 
				
			||||||
	case "":
 | 
					 | 
				
			||||||
		dir = "."
 | 
					 | 
				
			||||||
	case string(filepath.Separator):
 | 
					 | 
				
			||||||
	// nothing
 | 
					 | 
				
			||||||
	default:
 | 
					 | 
				
			||||||
		dir = dir[0 : len(dir)-1] // chop off trailing separator
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if !hasMeta(dir) {
 | 
					 | 
				
			||||||
		return glob(fs, dir, file, nil)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	var m []string
 | 
					 | 
				
			||||||
	m, err = Glob(fs, dir)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	for _, d := range m {
 | 
					 | 
				
			||||||
		matches, err = glob(fs, d, file, matches)
 | 
					 | 
				
			||||||
		if err != nil {
 | 
					 | 
				
			||||||
			return
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// glob searches for files matching pattern in the directory dir
 | 
					 | 
				
			||||||
// and appends them to matches. If the directory cannot be
 | 
					 | 
				
			||||||
// opened, it returns the existing matches. New matches are
 | 
					 | 
				
			||||||
// added in lexicographical order.
 | 
					 | 
				
			||||||
func glob(fs Fs, dir, pattern string, matches []string) (m []string, e error) {
 | 
					 | 
				
			||||||
	m = matches
 | 
					 | 
				
			||||||
	fi, err := fs.Stat(dir)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if !fi.IsDir() {
 | 
					 | 
				
			||||||
		return
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	d, err := fs.Open(dir)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	defer d.Close()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	names, _ := d.Readdirnames(-1)
 | 
					 | 
				
			||||||
	sort.Strings(names)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	for _, n := range names {
 | 
					 | 
				
			||||||
		matched, err := filepath.Match(pattern, n)
 | 
					 | 
				
			||||||
		if err != nil {
 | 
					 | 
				
			||||||
			return m, err
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if matched {
 | 
					 | 
				
			||||||
			m = append(m, filepath.Join(dir, n))
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// hasMeta reports whether path contains any of the magic characters
 | 
					 | 
				
			||||||
// recognized by Match.
 | 
					 | 
				
			||||||
func hasMeta(path string) bool {
 | 
					 | 
				
			||||||
	// TODO(niemeyer): Should other magic characters be added here?
 | 
					 | 
				
			||||||
	return strings.IndexAny(path, "*?[") >= 0
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										37
									
								
								vendor/github.com/spf13/afero/mem/dir.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										37
									
								
								vendor/github.com/spf13/afero/mem/dir.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,37 +0,0 @@
 | 
				
			|||||||
// Copyright © 2014 Steve Francia <spf@spf13.com>.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
// 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.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
package mem
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type Dir interface {
 | 
					 | 
				
			||||||
	Len() int
 | 
					 | 
				
			||||||
	Names() []string
 | 
					 | 
				
			||||||
	Files() []*FileData
 | 
					 | 
				
			||||||
	Add(*FileData)
 | 
					 | 
				
			||||||
	Remove(*FileData)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func RemoveFromMemDir(dir *FileData, f *FileData) {
 | 
					 | 
				
			||||||
	dir.memDir.Remove(f)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func AddToMemDir(dir *FileData, f *FileData) {
 | 
					 | 
				
			||||||
	dir.memDir.Add(f)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func InitializeDir(d *FileData) {
 | 
					 | 
				
			||||||
	if d.memDir == nil {
 | 
					 | 
				
			||||||
		d.dir = true
 | 
					 | 
				
			||||||
		d.memDir = &DirMap{}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										43
									
								
								vendor/github.com/spf13/afero/mem/dirmap.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										43
									
								
								vendor/github.com/spf13/afero/mem/dirmap.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,43 +0,0 @@
 | 
				
			|||||||
// Copyright © 2015 Steve Francia <spf@spf13.com>.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
// 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.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
package mem
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import "sort"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type DirMap map[string]*FileData
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (m DirMap) Len() int           { return len(m) }
 | 
					 | 
				
			||||||
func (m DirMap) Add(f *FileData)    { m[f.name] = f }
 | 
					 | 
				
			||||||
func (m DirMap) Remove(f *FileData) { delete(m, f.name) }
 | 
					 | 
				
			||||||
func (m DirMap) Files() (files []*FileData) {
 | 
					 | 
				
			||||||
	for _, f := range m {
 | 
					 | 
				
			||||||
		files = append(files, f)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	sort.Sort(filesSorter(files))
 | 
					 | 
				
			||||||
	return files
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// implement sort.Interface for []*FileData
 | 
					 | 
				
			||||||
type filesSorter []*FileData
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (s filesSorter) Len() int           { return len(s) }
 | 
					 | 
				
			||||||
func (s filesSorter) Swap(i, j int)      { s[i], s[j] = s[j], s[i] }
 | 
					 | 
				
			||||||
func (s filesSorter) Less(i, j int) bool { return s[i].name < s[j].name }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (m DirMap) Names() (names []string) {
 | 
					 | 
				
			||||||
	for x := range m {
 | 
					 | 
				
			||||||
		names = append(names, x)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return names
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										317
									
								
								vendor/github.com/spf13/afero/mem/file.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										317
									
								
								vendor/github.com/spf13/afero/mem/file.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,317 +0,0 @@
 | 
				
			|||||||
// Copyright © 2015 Steve Francia <spf@spf13.com>.
 | 
					 | 
				
			||||||
// Copyright 2013 tsuru authors. All rights reserved.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
// 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.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
package mem
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"bytes"
 | 
					 | 
				
			||||||
	"errors"
 | 
					 | 
				
			||||||
	"io"
 | 
					 | 
				
			||||||
	"os"
 | 
					 | 
				
			||||||
	"path/filepath"
 | 
					 | 
				
			||||||
	"sync"
 | 
					 | 
				
			||||||
	"sync/atomic"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import "time"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const FilePathSeparator = string(filepath.Separator)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type File struct {
 | 
					 | 
				
			||||||
	// atomic requires 64-bit alignment for struct field access
 | 
					 | 
				
			||||||
	at           int64
 | 
					 | 
				
			||||||
	readDirCount int64
 | 
					 | 
				
			||||||
	closed       bool
 | 
					 | 
				
			||||||
	readOnly     bool
 | 
					 | 
				
			||||||
	fileData     *FileData
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func NewFileHandle(data *FileData) *File {
 | 
					 | 
				
			||||||
	return &File{fileData: data}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func NewReadOnlyFileHandle(data *FileData) *File {
 | 
					 | 
				
			||||||
	return &File{fileData: data, readOnly: true}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (f File) Data() *FileData {
 | 
					 | 
				
			||||||
	return f.fileData
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type FileData struct {
 | 
					 | 
				
			||||||
	sync.Mutex
 | 
					 | 
				
			||||||
	name    string
 | 
					 | 
				
			||||||
	data    []byte
 | 
					 | 
				
			||||||
	memDir  Dir
 | 
					 | 
				
			||||||
	dir     bool
 | 
					 | 
				
			||||||
	mode    os.FileMode
 | 
					 | 
				
			||||||
	modtime time.Time
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (d *FileData) Name() string {
 | 
					 | 
				
			||||||
	d.Lock()
 | 
					 | 
				
			||||||
	defer d.Unlock()
 | 
					 | 
				
			||||||
	return d.name
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func CreateFile(name string) *FileData {
 | 
					 | 
				
			||||||
	return &FileData{name: name, mode: os.ModeTemporary, modtime: time.Now()}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func CreateDir(name string) *FileData {
 | 
					 | 
				
			||||||
	return &FileData{name: name, memDir: &DirMap{}, dir: true}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func ChangeFileName(f *FileData, newname string) {
 | 
					 | 
				
			||||||
	f.Lock()
 | 
					 | 
				
			||||||
	f.name = newname
 | 
					 | 
				
			||||||
	f.Unlock()
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func SetMode(f *FileData, mode os.FileMode) {
 | 
					 | 
				
			||||||
	f.Lock()
 | 
					 | 
				
			||||||
	f.mode = mode
 | 
					 | 
				
			||||||
	f.Unlock()
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func SetModTime(f *FileData, mtime time.Time) {
 | 
					 | 
				
			||||||
	f.Lock()
 | 
					 | 
				
			||||||
	setModTime(f, mtime)
 | 
					 | 
				
			||||||
	f.Unlock()
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func setModTime(f *FileData, mtime time.Time) {
 | 
					 | 
				
			||||||
	f.modtime = mtime
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func GetFileInfo(f *FileData) *FileInfo {
 | 
					 | 
				
			||||||
	return &FileInfo{f}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (f *File) Open() error {
 | 
					 | 
				
			||||||
	atomic.StoreInt64(&f.at, 0)
 | 
					 | 
				
			||||||
	atomic.StoreInt64(&f.readDirCount, 0)
 | 
					 | 
				
			||||||
	f.fileData.Lock()
 | 
					 | 
				
			||||||
	f.closed = false
 | 
					 | 
				
			||||||
	f.fileData.Unlock()
 | 
					 | 
				
			||||||
	return nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (f *File) Close() error {
 | 
					 | 
				
			||||||
	f.fileData.Lock()
 | 
					 | 
				
			||||||
	f.closed = true
 | 
					 | 
				
			||||||
	if !f.readOnly {
 | 
					 | 
				
			||||||
		setModTime(f.fileData, time.Now())
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	f.fileData.Unlock()
 | 
					 | 
				
			||||||
	return nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (f *File) Name() string {
 | 
					 | 
				
			||||||
	return f.fileData.Name()
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (f *File) Stat() (os.FileInfo, error) {
 | 
					 | 
				
			||||||
	return &FileInfo{f.fileData}, nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (f *File) Sync() error {
 | 
					 | 
				
			||||||
	return nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (f *File) Readdir(count int) (res []os.FileInfo, err error) {
 | 
					 | 
				
			||||||
	if !f.fileData.dir {
 | 
					 | 
				
			||||||
		return nil, &os.PathError{Op: "readdir", Path: f.fileData.name, Err: errors.New("not a dir")}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	var outLength int64
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	f.fileData.Lock()
 | 
					 | 
				
			||||||
	files := f.fileData.memDir.Files()[f.readDirCount:]
 | 
					 | 
				
			||||||
	if count > 0 {
 | 
					 | 
				
			||||||
		if len(files) < count {
 | 
					 | 
				
			||||||
			outLength = int64(len(files))
 | 
					 | 
				
			||||||
		} else {
 | 
					 | 
				
			||||||
			outLength = int64(count)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if len(files) == 0 {
 | 
					 | 
				
			||||||
			err = io.EOF
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		outLength = int64(len(files))
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	f.readDirCount += outLength
 | 
					 | 
				
			||||||
	f.fileData.Unlock()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	res = make([]os.FileInfo, outLength)
 | 
					 | 
				
			||||||
	for i := range res {
 | 
					 | 
				
			||||||
		res[i] = &FileInfo{files[i]}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return res, err
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (f *File) Readdirnames(n int) (names []string, err error) {
 | 
					 | 
				
			||||||
	fi, err := f.Readdir(n)
 | 
					 | 
				
			||||||
	names = make([]string, len(fi))
 | 
					 | 
				
			||||||
	for i, f := range fi {
 | 
					 | 
				
			||||||
		_, names[i] = filepath.Split(f.Name())
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return names, err
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (f *File) Read(b []byte) (n int, err error) {
 | 
					 | 
				
			||||||
	f.fileData.Lock()
 | 
					 | 
				
			||||||
	defer f.fileData.Unlock()
 | 
					 | 
				
			||||||
	if f.closed == true {
 | 
					 | 
				
			||||||
		return 0, ErrFileClosed
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if len(b) > 0 && int(f.at) == len(f.fileData.data) {
 | 
					 | 
				
			||||||
		return 0, io.EOF
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if int(f.at) > len(f.fileData.data) {
 | 
					 | 
				
			||||||
		return 0, io.ErrUnexpectedEOF
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if len(f.fileData.data)-int(f.at) >= len(b) {
 | 
					 | 
				
			||||||
		n = len(b)
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		n = len(f.fileData.data) - int(f.at)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	copy(b, f.fileData.data[f.at:f.at+int64(n)])
 | 
					 | 
				
			||||||
	atomic.AddInt64(&f.at, int64(n))
 | 
					 | 
				
			||||||
	return
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (f *File) ReadAt(b []byte, off int64) (n int, err error) {
 | 
					 | 
				
			||||||
	atomic.StoreInt64(&f.at, off)
 | 
					 | 
				
			||||||
	return f.Read(b)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (f *File) Truncate(size int64) error {
 | 
					 | 
				
			||||||
	if f.closed == true {
 | 
					 | 
				
			||||||
		return ErrFileClosed
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if f.readOnly {
 | 
					 | 
				
			||||||
		return &os.PathError{Op: "truncate", Path: f.fileData.name, Err: errors.New("file handle is read only")}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if size < 0 {
 | 
					 | 
				
			||||||
		return ErrOutOfRange
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if size > int64(len(f.fileData.data)) {
 | 
					 | 
				
			||||||
		diff := size - int64(len(f.fileData.data))
 | 
					 | 
				
			||||||
		f.fileData.data = append(f.fileData.data, bytes.Repeat([]byte{00}, int(diff))...)
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		f.fileData.data = f.fileData.data[0:size]
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	setModTime(f.fileData, time.Now())
 | 
					 | 
				
			||||||
	return nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (f *File) Seek(offset int64, whence int) (int64, error) {
 | 
					 | 
				
			||||||
	if f.closed == true {
 | 
					 | 
				
			||||||
		return 0, ErrFileClosed
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	switch whence {
 | 
					 | 
				
			||||||
	case 0:
 | 
					 | 
				
			||||||
		atomic.StoreInt64(&f.at, offset)
 | 
					 | 
				
			||||||
	case 1:
 | 
					 | 
				
			||||||
		atomic.AddInt64(&f.at, int64(offset))
 | 
					 | 
				
			||||||
	case 2:
 | 
					 | 
				
			||||||
		atomic.StoreInt64(&f.at, int64(len(f.fileData.data))+offset)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return f.at, nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (f *File) Write(b []byte) (n int, err error) {
 | 
					 | 
				
			||||||
	if f.readOnly {
 | 
					 | 
				
			||||||
		return 0, &os.PathError{Op: "write", Path: f.fileData.name, Err: errors.New("file handle is read only")}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	n = len(b)
 | 
					 | 
				
			||||||
	cur := atomic.LoadInt64(&f.at)
 | 
					 | 
				
			||||||
	f.fileData.Lock()
 | 
					 | 
				
			||||||
	defer f.fileData.Unlock()
 | 
					 | 
				
			||||||
	diff := cur - int64(len(f.fileData.data))
 | 
					 | 
				
			||||||
	var tail []byte
 | 
					 | 
				
			||||||
	if n+int(cur) < len(f.fileData.data) {
 | 
					 | 
				
			||||||
		tail = f.fileData.data[n+int(cur):]
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if diff > 0 {
 | 
					 | 
				
			||||||
		f.fileData.data = append(bytes.Repeat([]byte{00}, int(diff)), b...)
 | 
					 | 
				
			||||||
		f.fileData.data = append(f.fileData.data, tail...)
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		f.fileData.data = append(f.fileData.data[:cur], b...)
 | 
					 | 
				
			||||||
		f.fileData.data = append(f.fileData.data, tail...)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	setModTime(f.fileData, time.Now())
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	atomic.StoreInt64(&f.at, int64(len(f.fileData.data)))
 | 
					 | 
				
			||||||
	return
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (f *File) WriteAt(b []byte, off int64) (n int, err error) {
 | 
					 | 
				
			||||||
	atomic.StoreInt64(&f.at, off)
 | 
					 | 
				
			||||||
	return f.Write(b)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (f *File) WriteString(s string) (ret int, err error) {
 | 
					 | 
				
			||||||
	return f.Write([]byte(s))
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (f *File) Info() *FileInfo {
 | 
					 | 
				
			||||||
	return &FileInfo{f.fileData}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type FileInfo struct {
 | 
					 | 
				
			||||||
	*FileData
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Implements os.FileInfo
 | 
					 | 
				
			||||||
func (s *FileInfo) Name() string {
 | 
					 | 
				
			||||||
	s.Lock()
 | 
					 | 
				
			||||||
	_, name := filepath.Split(s.name)
 | 
					 | 
				
			||||||
	s.Unlock()
 | 
					 | 
				
			||||||
	return name
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
func (s *FileInfo) Mode() os.FileMode {
 | 
					 | 
				
			||||||
	s.Lock()
 | 
					 | 
				
			||||||
	defer s.Unlock()
 | 
					 | 
				
			||||||
	return s.mode
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
func (s *FileInfo) ModTime() time.Time {
 | 
					 | 
				
			||||||
	s.Lock()
 | 
					 | 
				
			||||||
	defer s.Unlock()
 | 
					 | 
				
			||||||
	return s.modtime
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
func (s *FileInfo) IsDir() bool {
 | 
					 | 
				
			||||||
	s.Lock()
 | 
					 | 
				
			||||||
	defer s.Unlock()
 | 
					 | 
				
			||||||
	return s.dir
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
func (s *FileInfo) Sys() interface{} { return nil }
 | 
					 | 
				
			||||||
func (s *FileInfo) Size() int64 {
 | 
					 | 
				
			||||||
	if s.IsDir() {
 | 
					 | 
				
			||||||
		return int64(42)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	s.Lock()
 | 
					 | 
				
			||||||
	defer s.Unlock()
 | 
					 | 
				
			||||||
	return int64(len(s.data))
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var (
 | 
					 | 
				
			||||||
	ErrFileClosed        = errors.New("File is closed")
 | 
					 | 
				
			||||||
	ErrOutOfRange        = errors.New("Out of range")
 | 
					 | 
				
			||||||
	ErrTooLarge          = errors.New("Too large")
 | 
					 | 
				
			||||||
	ErrFileNotFound      = os.ErrNotExist
 | 
					 | 
				
			||||||
	ErrFileExists        = os.ErrExist
 | 
					 | 
				
			||||||
	ErrDestinationExists = os.ErrExist
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
							
								
								
									
										365
									
								
								vendor/github.com/spf13/afero/memmap.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										365
									
								
								vendor/github.com/spf13/afero/memmap.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,365 +0,0 @@
 | 
				
			|||||||
// Copyright © 2014 Steve Francia <spf@spf13.com>.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
// 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.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
package afero
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"fmt"
 | 
					 | 
				
			||||||
	"log"
 | 
					 | 
				
			||||||
	"os"
 | 
					 | 
				
			||||||
	"path/filepath"
 | 
					 | 
				
			||||||
	"strings"
 | 
					 | 
				
			||||||
	"sync"
 | 
					 | 
				
			||||||
	"time"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	"github.com/spf13/afero/mem"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type MemMapFs struct {
 | 
					 | 
				
			||||||
	mu   sync.RWMutex
 | 
					 | 
				
			||||||
	data map[string]*mem.FileData
 | 
					 | 
				
			||||||
	init sync.Once
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func NewMemMapFs() Fs {
 | 
					 | 
				
			||||||
	return &MemMapFs{}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (m *MemMapFs) getData() map[string]*mem.FileData {
 | 
					 | 
				
			||||||
	m.init.Do(func() {
 | 
					 | 
				
			||||||
		m.data = make(map[string]*mem.FileData)
 | 
					 | 
				
			||||||
		// Root should always exist, right?
 | 
					 | 
				
			||||||
		// TODO: what about windows?
 | 
					 | 
				
			||||||
		m.data[FilePathSeparator] = mem.CreateDir(FilePathSeparator)
 | 
					 | 
				
			||||||
	})
 | 
					 | 
				
			||||||
	return m.data
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (*MemMapFs) Name() string { return "MemMapFS" }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (m *MemMapFs) Create(name string) (File, error) {
 | 
					 | 
				
			||||||
	name = normalizePath(name)
 | 
					 | 
				
			||||||
	m.mu.Lock()
 | 
					 | 
				
			||||||
	file := mem.CreateFile(name)
 | 
					 | 
				
			||||||
	m.getData()[name] = file
 | 
					 | 
				
			||||||
	m.registerWithParent(file)
 | 
					 | 
				
			||||||
	m.mu.Unlock()
 | 
					 | 
				
			||||||
	return mem.NewFileHandle(file), nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (m *MemMapFs) unRegisterWithParent(fileName string) error {
 | 
					 | 
				
			||||||
	f, err := m.lockfreeOpen(fileName)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	parent := m.findParent(f)
 | 
					 | 
				
			||||||
	if parent == nil {
 | 
					 | 
				
			||||||
		log.Panic("parent of ", f.Name(), " is nil")
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	parent.Lock()
 | 
					 | 
				
			||||||
	mem.RemoveFromMemDir(parent, f)
 | 
					 | 
				
			||||||
	parent.Unlock()
 | 
					 | 
				
			||||||
	return nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (m *MemMapFs) findParent(f *mem.FileData) *mem.FileData {
 | 
					 | 
				
			||||||
	pdir, _ := filepath.Split(f.Name())
 | 
					 | 
				
			||||||
	pdir = filepath.Clean(pdir)
 | 
					 | 
				
			||||||
	pfile, err := m.lockfreeOpen(pdir)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return nil
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return pfile
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (m *MemMapFs) registerWithParent(f *mem.FileData) {
 | 
					 | 
				
			||||||
	if f == nil {
 | 
					 | 
				
			||||||
		return
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	parent := m.findParent(f)
 | 
					 | 
				
			||||||
	if parent == nil {
 | 
					 | 
				
			||||||
		pdir := filepath.Dir(filepath.Clean(f.Name()))
 | 
					 | 
				
			||||||
		err := m.lockfreeMkdir(pdir, 0777)
 | 
					 | 
				
			||||||
		if err != nil {
 | 
					 | 
				
			||||||
			//log.Println("Mkdir error:", err)
 | 
					 | 
				
			||||||
			return
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		parent, err = m.lockfreeOpen(pdir)
 | 
					 | 
				
			||||||
		if err != nil {
 | 
					 | 
				
			||||||
			//log.Println("Open after Mkdir error:", err)
 | 
					 | 
				
			||||||
			return
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	parent.Lock()
 | 
					 | 
				
			||||||
	mem.InitializeDir(parent)
 | 
					 | 
				
			||||||
	mem.AddToMemDir(parent, f)
 | 
					 | 
				
			||||||
	parent.Unlock()
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (m *MemMapFs) lockfreeMkdir(name string, perm os.FileMode) error {
 | 
					 | 
				
			||||||
	name = normalizePath(name)
 | 
					 | 
				
			||||||
	x, ok := m.getData()[name]
 | 
					 | 
				
			||||||
	if ok {
 | 
					 | 
				
			||||||
		// Only return ErrFileExists if it's a file, not a directory.
 | 
					 | 
				
			||||||
		i := mem.FileInfo{FileData: x}
 | 
					 | 
				
			||||||
		if !i.IsDir() {
 | 
					 | 
				
			||||||
			return ErrFileExists
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		item := mem.CreateDir(name)
 | 
					 | 
				
			||||||
		m.getData()[name] = item
 | 
					 | 
				
			||||||
		m.registerWithParent(item)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (m *MemMapFs) Mkdir(name string, perm os.FileMode) error {
 | 
					 | 
				
			||||||
	name = normalizePath(name)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	m.mu.RLock()
 | 
					 | 
				
			||||||
	_, ok := m.getData()[name]
 | 
					 | 
				
			||||||
	m.mu.RUnlock()
 | 
					 | 
				
			||||||
	if ok {
 | 
					 | 
				
			||||||
		return &os.PathError{Op: "mkdir", Path: name, Err: ErrFileExists}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	m.mu.Lock()
 | 
					 | 
				
			||||||
	item := mem.CreateDir(name)
 | 
					 | 
				
			||||||
	m.getData()[name] = item
 | 
					 | 
				
			||||||
	m.registerWithParent(item)
 | 
					 | 
				
			||||||
	m.mu.Unlock()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	m.Chmod(name, perm|os.ModeDir)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (m *MemMapFs) MkdirAll(path string, perm os.FileMode) error {
 | 
					 | 
				
			||||||
	err := m.Mkdir(path, perm)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		if err.(*os.PathError).Err == ErrFileExists {
 | 
					 | 
				
			||||||
			return nil
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		return err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Handle some relative paths
 | 
					 | 
				
			||||||
func normalizePath(path string) string {
 | 
					 | 
				
			||||||
	path = filepath.Clean(path)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	switch path {
 | 
					 | 
				
			||||||
	case ".":
 | 
					 | 
				
			||||||
		return FilePathSeparator
 | 
					 | 
				
			||||||
	case "..":
 | 
					 | 
				
			||||||
		return FilePathSeparator
 | 
					 | 
				
			||||||
	default:
 | 
					 | 
				
			||||||
		return path
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (m *MemMapFs) Open(name string) (File, error) {
 | 
					 | 
				
			||||||
	f, err := m.open(name)
 | 
					 | 
				
			||||||
	if f != nil {
 | 
					 | 
				
			||||||
		return mem.NewReadOnlyFileHandle(f), err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return nil, err
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (m *MemMapFs) openWrite(name string) (File, error) {
 | 
					 | 
				
			||||||
	f, err := m.open(name)
 | 
					 | 
				
			||||||
	if f != nil {
 | 
					 | 
				
			||||||
		return mem.NewFileHandle(f), err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return nil, err
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (m *MemMapFs) open(name string) (*mem.FileData, error) {
 | 
					 | 
				
			||||||
	name = normalizePath(name)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	m.mu.RLock()
 | 
					 | 
				
			||||||
	f, ok := m.getData()[name]
 | 
					 | 
				
			||||||
	m.mu.RUnlock()
 | 
					 | 
				
			||||||
	if !ok {
 | 
					 | 
				
			||||||
		return nil, &os.PathError{Op: "open", Path: name, Err: ErrFileNotFound}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return f, nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (m *MemMapFs) lockfreeOpen(name string) (*mem.FileData, error) {
 | 
					 | 
				
			||||||
	name = normalizePath(name)
 | 
					 | 
				
			||||||
	f, ok := m.getData()[name]
 | 
					 | 
				
			||||||
	if ok {
 | 
					 | 
				
			||||||
		return f, nil
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		return nil, ErrFileNotFound
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (m *MemMapFs) OpenFile(name string, flag int, perm os.FileMode) (File, error) {
 | 
					 | 
				
			||||||
	chmod := false
 | 
					 | 
				
			||||||
	file, err := m.openWrite(name)
 | 
					 | 
				
			||||||
	if os.IsNotExist(err) && (flag&os.O_CREATE > 0) {
 | 
					 | 
				
			||||||
		file, err = m.Create(name)
 | 
					 | 
				
			||||||
		chmod = true
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return nil, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if flag == os.O_RDONLY {
 | 
					 | 
				
			||||||
		file = mem.NewReadOnlyFileHandle(file.(*mem.File).Data())
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if flag&os.O_APPEND > 0 {
 | 
					 | 
				
			||||||
		_, err = file.Seek(0, os.SEEK_END)
 | 
					 | 
				
			||||||
		if err != nil {
 | 
					 | 
				
			||||||
			file.Close()
 | 
					 | 
				
			||||||
			return nil, err
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if flag&os.O_TRUNC > 0 && flag&(os.O_RDWR|os.O_WRONLY) > 0 {
 | 
					 | 
				
			||||||
		err = file.Truncate(0)
 | 
					 | 
				
			||||||
		if err != nil {
 | 
					 | 
				
			||||||
			file.Close()
 | 
					 | 
				
			||||||
			return nil, err
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if chmod {
 | 
					 | 
				
			||||||
		m.Chmod(name, perm)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return file, nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (m *MemMapFs) Remove(name string) error {
 | 
					 | 
				
			||||||
	name = normalizePath(name)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	m.mu.Lock()
 | 
					 | 
				
			||||||
	defer m.mu.Unlock()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if _, ok := m.getData()[name]; ok {
 | 
					 | 
				
			||||||
		err := m.unRegisterWithParent(name)
 | 
					 | 
				
			||||||
		if err != nil {
 | 
					 | 
				
			||||||
			return &os.PathError{Op: "remove", Path: name, Err: err}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		delete(m.getData(), name)
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		return &os.PathError{Op: "remove", Path: name, Err: os.ErrNotExist}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (m *MemMapFs) RemoveAll(path string) error {
 | 
					 | 
				
			||||||
	path = normalizePath(path)
 | 
					 | 
				
			||||||
	m.mu.Lock()
 | 
					 | 
				
			||||||
	m.unRegisterWithParent(path)
 | 
					 | 
				
			||||||
	m.mu.Unlock()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	m.mu.RLock()
 | 
					 | 
				
			||||||
	defer m.mu.RUnlock()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	for p, _ := range m.getData() {
 | 
					 | 
				
			||||||
		if strings.HasPrefix(p, path) {
 | 
					 | 
				
			||||||
			m.mu.RUnlock()
 | 
					 | 
				
			||||||
			m.mu.Lock()
 | 
					 | 
				
			||||||
			delete(m.getData(), p)
 | 
					 | 
				
			||||||
			m.mu.Unlock()
 | 
					 | 
				
			||||||
			m.mu.RLock()
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (m *MemMapFs) Rename(oldname, newname string) error {
 | 
					 | 
				
			||||||
	oldname = normalizePath(oldname)
 | 
					 | 
				
			||||||
	newname = normalizePath(newname)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if oldname == newname {
 | 
					 | 
				
			||||||
		return nil
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	m.mu.RLock()
 | 
					 | 
				
			||||||
	defer m.mu.RUnlock()
 | 
					 | 
				
			||||||
	if _, ok := m.getData()[oldname]; ok {
 | 
					 | 
				
			||||||
		m.mu.RUnlock()
 | 
					 | 
				
			||||||
		m.mu.Lock()
 | 
					 | 
				
			||||||
		m.unRegisterWithParent(oldname)
 | 
					 | 
				
			||||||
		fileData := m.getData()[oldname]
 | 
					 | 
				
			||||||
		delete(m.getData(), oldname)
 | 
					 | 
				
			||||||
		mem.ChangeFileName(fileData, newname)
 | 
					 | 
				
			||||||
		m.getData()[newname] = fileData
 | 
					 | 
				
			||||||
		m.registerWithParent(fileData)
 | 
					 | 
				
			||||||
		m.mu.Unlock()
 | 
					 | 
				
			||||||
		m.mu.RLock()
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		return &os.PathError{Op: "rename", Path: oldname, Err: ErrFileNotFound}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (m *MemMapFs) Stat(name string) (os.FileInfo, error) {
 | 
					 | 
				
			||||||
	f, err := m.Open(name)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return nil, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	fi := mem.GetFileInfo(f.(*mem.File).Data())
 | 
					 | 
				
			||||||
	return fi, nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (m *MemMapFs) Chmod(name string, mode os.FileMode) error {
 | 
					 | 
				
			||||||
	name = normalizePath(name)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	m.mu.RLock()
 | 
					 | 
				
			||||||
	f, ok := m.getData()[name]
 | 
					 | 
				
			||||||
	m.mu.RUnlock()
 | 
					 | 
				
			||||||
	if !ok {
 | 
					 | 
				
			||||||
		return &os.PathError{Op: "chmod", Path: name, Err: ErrFileNotFound}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	m.mu.Lock()
 | 
					 | 
				
			||||||
	mem.SetMode(f, mode)
 | 
					 | 
				
			||||||
	m.mu.Unlock()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (m *MemMapFs) Chtimes(name string, atime time.Time, mtime time.Time) error {
 | 
					 | 
				
			||||||
	name = normalizePath(name)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	m.mu.RLock()
 | 
					 | 
				
			||||||
	f, ok := m.getData()[name]
 | 
					 | 
				
			||||||
	m.mu.RUnlock()
 | 
					 | 
				
			||||||
	if !ok {
 | 
					 | 
				
			||||||
		return &os.PathError{Op: "chtimes", Path: name, Err: ErrFileNotFound}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	m.mu.Lock()
 | 
					 | 
				
			||||||
	mem.SetModTime(f, mtime)
 | 
					 | 
				
			||||||
	m.mu.Unlock()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (m *MemMapFs) List() {
 | 
					 | 
				
			||||||
	for _, x := range m.data {
 | 
					 | 
				
			||||||
		y := mem.FileInfo{FileData: x}
 | 
					 | 
				
			||||||
		fmt.Println(x.Name(), y.Size())
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// func debugMemMapList(fs Fs) {
 | 
					 | 
				
			||||||
// 	if x, ok := fs.(*MemMapFs); ok {
 | 
					 | 
				
			||||||
// 		x.List()
 | 
					 | 
				
			||||||
// 	}
 | 
					 | 
				
			||||||
// }
 | 
					 | 
				
			||||||
							
								
								
									
										101
									
								
								vendor/github.com/spf13/afero/os.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										101
									
								
								vendor/github.com/spf13/afero/os.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,101 +0,0 @@
 | 
				
			|||||||
// Copyright © 2014 Steve Francia <spf@spf13.com>.
 | 
					 | 
				
			||||||
// Copyright 2013 tsuru authors. All rights reserved.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
// 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.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
package afero
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"os"
 | 
					 | 
				
			||||||
	"time"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var _ Lstater = (*OsFs)(nil)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// OsFs is a Fs implementation that uses functions provided by the os package.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
// For details in any method, check the documentation of the os package
 | 
					 | 
				
			||||||
// (http://golang.org/pkg/os/).
 | 
					 | 
				
			||||||
type OsFs struct{}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func NewOsFs() Fs {
 | 
					 | 
				
			||||||
	return &OsFs{}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (OsFs) Name() string { return "OsFs" }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (OsFs) Create(name string) (File, error) {
 | 
					 | 
				
			||||||
	f, e := os.Create(name)
 | 
					 | 
				
			||||||
	if f == nil {
 | 
					 | 
				
			||||||
		// while this looks strange, we need to return a bare nil (of type nil) not
 | 
					 | 
				
			||||||
		// a nil value of type *os.File or nil won't be nil
 | 
					 | 
				
			||||||
		return nil, e
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return f, e
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (OsFs) Mkdir(name string, perm os.FileMode) error {
 | 
					 | 
				
			||||||
	return os.Mkdir(name, perm)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (OsFs) MkdirAll(path string, perm os.FileMode) error {
 | 
					 | 
				
			||||||
	return os.MkdirAll(path, perm)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (OsFs) Open(name string) (File, error) {
 | 
					 | 
				
			||||||
	f, e := os.Open(name)
 | 
					 | 
				
			||||||
	if f == nil {
 | 
					 | 
				
			||||||
		// while this looks strange, we need to return a bare nil (of type nil) not
 | 
					 | 
				
			||||||
		// a nil value of type *os.File or nil won't be nil
 | 
					 | 
				
			||||||
		return nil, e
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return f, e
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (OsFs) OpenFile(name string, flag int, perm os.FileMode) (File, error) {
 | 
					 | 
				
			||||||
	f, e := os.OpenFile(name, flag, perm)
 | 
					 | 
				
			||||||
	if f == nil {
 | 
					 | 
				
			||||||
		// while this looks strange, we need to return a bare nil (of type nil) not
 | 
					 | 
				
			||||||
		// a nil value of type *os.File or nil won't be nil
 | 
					 | 
				
			||||||
		return nil, e
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return f, e
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (OsFs) Remove(name string) error {
 | 
					 | 
				
			||||||
	return os.Remove(name)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (OsFs) RemoveAll(path string) error {
 | 
					 | 
				
			||||||
	return os.RemoveAll(path)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (OsFs) Rename(oldname, newname string) error {
 | 
					 | 
				
			||||||
	return os.Rename(oldname, newname)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (OsFs) Stat(name string) (os.FileInfo, error) {
 | 
					 | 
				
			||||||
	return os.Stat(name)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (OsFs) Chmod(name string, mode os.FileMode) error {
 | 
					 | 
				
			||||||
	return os.Chmod(name, mode)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (OsFs) Chtimes(name string, atime time.Time, mtime time.Time) error {
 | 
					 | 
				
			||||||
	return os.Chtimes(name, atime, mtime)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (OsFs) LstatIfPossible(name string) (os.FileInfo, bool, error) {
 | 
					 | 
				
			||||||
	fi, err := os.Lstat(name)
 | 
					 | 
				
			||||||
	return fi, true, err
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										106
									
								
								vendor/github.com/spf13/afero/path.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										106
									
								
								vendor/github.com/spf13/afero/path.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,106 +0,0 @@
 | 
				
			|||||||
// Copyright ©2015 The Go Authors
 | 
					 | 
				
			||||||
// Copyright ©2015 Steve Francia <spf@spf13.com>
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
// 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.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
package afero
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"os"
 | 
					 | 
				
			||||||
	"path/filepath"
 | 
					 | 
				
			||||||
	"sort"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// readDirNames reads the directory named by dirname and returns
 | 
					 | 
				
			||||||
// a sorted list of directory entries.
 | 
					 | 
				
			||||||
// adapted from https://golang.org/src/path/filepath/path.go
 | 
					 | 
				
			||||||
func readDirNames(fs Fs, dirname string) ([]string, error) {
 | 
					 | 
				
			||||||
	f, err := fs.Open(dirname)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return nil, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	names, err := f.Readdirnames(-1)
 | 
					 | 
				
			||||||
	f.Close()
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return nil, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	sort.Strings(names)
 | 
					 | 
				
			||||||
	return names, nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// walk recursively descends path, calling walkFn
 | 
					 | 
				
			||||||
// adapted from https://golang.org/src/path/filepath/path.go
 | 
					 | 
				
			||||||
func walk(fs Fs, path string, info os.FileInfo, walkFn filepath.WalkFunc) error {
 | 
					 | 
				
			||||||
	err := walkFn(path, info, nil)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		if info.IsDir() && err == filepath.SkipDir {
 | 
					 | 
				
			||||||
			return nil
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		return err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if !info.IsDir() {
 | 
					 | 
				
			||||||
		return nil
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	names, err := readDirNames(fs, path)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return walkFn(path, info, err)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	for _, name := range names {
 | 
					 | 
				
			||||||
		filename := filepath.Join(path, name)
 | 
					 | 
				
			||||||
		fileInfo, err := lstatIfPossible(fs, filename)
 | 
					 | 
				
			||||||
		if err != nil {
 | 
					 | 
				
			||||||
			if err := walkFn(filename, fileInfo, err); err != nil && err != filepath.SkipDir {
 | 
					 | 
				
			||||||
				return err
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		} else {
 | 
					 | 
				
			||||||
			err = walk(fs, filename, fileInfo, walkFn)
 | 
					 | 
				
			||||||
			if err != nil {
 | 
					 | 
				
			||||||
				if !fileInfo.IsDir() || err != filepath.SkipDir {
 | 
					 | 
				
			||||||
					return err
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// if the filesystem supports it, use Lstat, else use fs.Stat
 | 
					 | 
				
			||||||
func lstatIfPossible(fs Fs, path string) (os.FileInfo, error) {
 | 
					 | 
				
			||||||
	if lfs, ok := fs.(Lstater); ok {
 | 
					 | 
				
			||||||
		fi, _, err := lfs.LstatIfPossible(path)
 | 
					 | 
				
			||||||
		return fi, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return fs.Stat(path)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Walk walks the file tree rooted at root, calling walkFn for each file or
 | 
					 | 
				
			||||||
// directory in the tree, including root. All errors that arise visiting files
 | 
					 | 
				
			||||||
// and directories are filtered by walkFn. The files are walked in lexical
 | 
					 | 
				
			||||||
// order, which makes the output deterministic but means that for very
 | 
					 | 
				
			||||||
// large directories Walk can be inefficient.
 | 
					 | 
				
			||||||
// Walk does not follow symbolic links.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (a Afero) Walk(root string, walkFn filepath.WalkFunc) error {
 | 
					 | 
				
			||||||
	return Walk(a.Fs, root, walkFn)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func Walk(fs Fs, root string, walkFn filepath.WalkFunc) error {
 | 
					 | 
				
			||||||
	info, err := lstatIfPossible(fs, root)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return walkFn(root, nil, err)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return walk(fs, root, info, walkFn)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										80
									
								
								vendor/github.com/spf13/afero/readonlyfs.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										80
									
								
								vendor/github.com/spf13/afero/readonlyfs.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,80 +0,0 @@
 | 
				
			|||||||
package afero
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"os"
 | 
					 | 
				
			||||||
	"syscall"
 | 
					 | 
				
			||||||
	"time"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var _ Lstater = (*ReadOnlyFs)(nil)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type ReadOnlyFs struct {
 | 
					 | 
				
			||||||
	source Fs
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func NewReadOnlyFs(source Fs) Fs {
 | 
					 | 
				
			||||||
	return &ReadOnlyFs{source: source}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (r *ReadOnlyFs) ReadDir(name string) ([]os.FileInfo, error) {
 | 
					 | 
				
			||||||
	return ReadDir(r.source, name)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (r *ReadOnlyFs) Chtimes(n string, a, m time.Time) error {
 | 
					 | 
				
			||||||
	return syscall.EPERM
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (r *ReadOnlyFs) Chmod(n string, m os.FileMode) error {
 | 
					 | 
				
			||||||
	return syscall.EPERM
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (r *ReadOnlyFs) Name() string {
 | 
					 | 
				
			||||||
	return "ReadOnlyFilter"
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (r *ReadOnlyFs) Stat(name string) (os.FileInfo, error) {
 | 
					 | 
				
			||||||
	return r.source.Stat(name)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (r *ReadOnlyFs) LstatIfPossible(name string) (os.FileInfo, bool, error) {
 | 
					 | 
				
			||||||
	if lsf, ok := r.source.(Lstater); ok {
 | 
					 | 
				
			||||||
		return lsf.LstatIfPossible(name)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	fi, err := r.Stat(name)
 | 
					 | 
				
			||||||
	return fi, false, err
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (r *ReadOnlyFs) Rename(o, n string) error {
 | 
					 | 
				
			||||||
	return syscall.EPERM
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (r *ReadOnlyFs) RemoveAll(p string) error {
 | 
					 | 
				
			||||||
	return syscall.EPERM
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (r *ReadOnlyFs) Remove(n string) error {
 | 
					 | 
				
			||||||
	return syscall.EPERM
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (r *ReadOnlyFs) OpenFile(name string, flag int, perm os.FileMode) (File, error) {
 | 
					 | 
				
			||||||
	if flag&(os.O_WRONLY|syscall.O_RDWR|os.O_APPEND|os.O_CREATE|os.O_TRUNC) != 0 {
 | 
					 | 
				
			||||||
		return nil, syscall.EPERM
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return r.source.OpenFile(name, flag, perm)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (r *ReadOnlyFs) Open(n string) (File, error) {
 | 
					 | 
				
			||||||
	return r.source.Open(n)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (r *ReadOnlyFs) Mkdir(n string, p os.FileMode) error {
 | 
					 | 
				
			||||||
	return syscall.EPERM
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (r *ReadOnlyFs) MkdirAll(n string, p os.FileMode) error {
 | 
					 | 
				
			||||||
	return syscall.EPERM
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (r *ReadOnlyFs) Create(n string) (File, error) {
 | 
					 | 
				
			||||||
	return nil, syscall.EPERM
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										214
									
								
								vendor/github.com/spf13/afero/regexpfs.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										214
									
								
								vendor/github.com/spf13/afero/regexpfs.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,214 +0,0 @@
 | 
				
			|||||||
package afero
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"os"
 | 
					 | 
				
			||||||
	"regexp"
 | 
					 | 
				
			||||||
	"syscall"
 | 
					 | 
				
			||||||
	"time"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// The RegexpFs filters files (not directories) by regular expression. Only
 | 
					 | 
				
			||||||
// files matching the given regexp will be allowed, all others get a ENOENT error (
 | 
					 | 
				
			||||||
// "No such file or directory").
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
type RegexpFs struct {
 | 
					 | 
				
			||||||
	re     *regexp.Regexp
 | 
					 | 
				
			||||||
	source Fs
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func NewRegexpFs(source Fs, re *regexp.Regexp) Fs {
 | 
					 | 
				
			||||||
	return &RegexpFs{source: source, re: re}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type RegexpFile struct {
 | 
					 | 
				
			||||||
	f  File
 | 
					 | 
				
			||||||
	re *regexp.Regexp
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (r *RegexpFs) matchesName(name string) error {
 | 
					 | 
				
			||||||
	if r.re == nil {
 | 
					 | 
				
			||||||
		return nil
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if r.re.MatchString(name) {
 | 
					 | 
				
			||||||
		return nil
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return syscall.ENOENT
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (r *RegexpFs) dirOrMatches(name string) error {
 | 
					 | 
				
			||||||
	dir, err := IsDir(r.source, name)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if dir {
 | 
					 | 
				
			||||||
		return nil
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return r.matchesName(name)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (r *RegexpFs) Chtimes(name string, a, m time.Time) error {
 | 
					 | 
				
			||||||
	if err := r.dirOrMatches(name); err != nil {
 | 
					 | 
				
			||||||
		return err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return r.source.Chtimes(name, a, m)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (r *RegexpFs) Chmod(name string, mode os.FileMode) error {
 | 
					 | 
				
			||||||
	if err := r.dirOrMatches(name); err != nil {
 | 
					 | 
				
			||||||
		return err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return r.source.Chmod(name, mode)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (r *RegexpFs) Name() string {
 | 
					 | 
				
			||||||
	return "RegexpFs"
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (r *RegexpFs) Stat(name string) (os.FileInfo, error) {
 | 
					 | 
				
			||||||
	if err := r.dirOrMatches(name); err != nil {
 | 
					 | 
				
			||||||
		return nil, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return r.source.Stat(name)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (r *RegexpFs) Rename(oldname, newname string) error {
 | 
					 | 
				
			||||||
	dir, err := IsDir(r.source, oldname)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if dir {
 | 
					 | 
				
			||||||
		return nil
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if err := r.matchesName(oldname); err != nil {
 | 
					 | 
				
			||||||
		return err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if err := r.matchesName(newname); err != nil {
 | 
					 | 
				
			||||||
		return err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return r.source.Rename(oldname, newname)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (r *RegexpFs) RemoveAll(p string) error {
 | 
					 | 
				
			||||||
	dir, err := IsDir(r.source, p)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if !dir {
 | 
					 | 
				
			||||||
		if err := r.matchesName(p); err != nil {
 | 
					 | 
				
			||||||
			return err
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return r.source.RemoveAll(p)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (r *RegexpFs) Remove(name string) error {
 | 
					 | 
				
			||||||
	if err := r.dirOrMatches(name); err != nil {
 | 
					 | 
				
			||||||
		return err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return r.source.Remove(name)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (r *RegexpFs) OpenFile(name string, flag int, perm os.FileMode) (File, error) {
 | 
					 | 
				
			||||||
	if err := r.dirOrMatches(name); err != nil {
 | 
					 | 
				
			||||||
		return nil, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return r.source.OpenFile(name, flag, perm)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (r *RegexpFs) Open(name string) (File, error) {
 | 
					 | 
				
			||||||
	dir, err := IsDir(r.source, name)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return nil, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if !dir {
 | 
					 | 
				
			||||||
		if err := r.matchesName(name); err != nil {
 | 
					 | 
				
			||||||
			return nil, err
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	f, err := r.source.Open(name)
 | 
					 | 
				
			||||||
	return &RegexpFile{f: f, re: r.re}, nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (r *RegexpFs) Mkdir(n string, p os.FileMode) error {
 | 
					 | 
				
			||||||
	return r.source.Mkdir(n, p)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (r *RegexpFs) MkdirAll(n string, p os.FileMode) error {
 | 
					 | 
				
			||||||
	return r.source.MkdirAll(n, p)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (r *RegexpFs) Create(name string) (File, error) {
 | 
					 | 
				
			||||||
	if err := r.matchesName(name); err != nil {
 | 
					 | 
				
			||||||
		return nil, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return r.source.Create(name)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (f *RegexpFile) Close() error {
 | 
					 | 
				
			||||||
	return f.f.Close()
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (f *RegexpFile) Read(s []byte) (int, error) {
 | 
					 | 
				
			||||||
	return f.f.Read(s)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (f *RegexpFile) ReadAt(s []byte, o int64) (int, error) {
 | 
					 | 
				
			||||||
	return f.f.ReadAt(s, o)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (f *RegexpFile) Seek(o int64, w int) (int64, error) {
 | 
					 | 
				
			||||||
	return f.f.Seek(o, w)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (f *RegexpFile) Write(s []byte) (int, error) {
 | 
					 | 
				
			||||||
	return f.f.Write(s)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (f *RegexpFile) WriteAt(s []byte, o int64) (int, error) {
 | 
					 | 
				
			||||||
	return f.f.WriteAt(s, o)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (f *RegexpFile) Name() string {
 | 
					 | 
				
			||||||
	return f.f.Name()
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (f *RegexpFile) Readdir(c int) (fi []os.FileInfo, err error) {
 | 
					 | 
				
			||||||
	var rfi []os.FileInfo
 | 
					 | 
				
			||||||
	rfi, err = f.f.Readdir(c)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return nil, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	for _, i := range rfi {
 | 
					 | 
				
			||||||
		if i.IsDir() || f.re.MatchString(i.Name()) {
 | 
					 | 
				
			||||||
			fi = append(fi, i)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return fi, nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (f *RegexpFile) Readdirnames(c int) (n []string, err error) {
 | 
					 | 
				
			||||||
	fi, err := f.Readdir(c)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return nil, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	for _, s := range fi {
 | 
					 | 
				
			||||||
		n = append(n, s.Name())
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return n, nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (f *RegexpFile) Stat() (os.FileInfo, error) {
 | 
					 | 
				
			||||||
	return f.f.Stat()
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (f *RegexpFile) Sync() error {
 | 
					 | 
				
			||||||
	return f.f.Sync()
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (f *RegexpFile) Truncate(s int64) error {
 | 
					 | 
				
			||||||
	return f.f.Truncate(s)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (f *RegexpFile) WriteString(s string) (int, error) {
 | 
					 | 
				
			||||||
	return f.f.WriteString(s)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										320
									
								
								vendor/github.com/spf13/afero/unionFile.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										320
									
								
								vendor/github.com/spf13/afero/unionFile.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,320 +0,0 @@
 | 
				
			|||||||
package afero
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"io"
 | 
					 | 
				
			||||||
	"os"
 | 
					 | 
				
			||||||
	"path/filepath"
 | 
					 | 
				
			||||||
	"syscall"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// The UnionFile implements the afero.File interface and will be returned
 | 
					 | 
				
			||||||
// when reading a directory present at least in the overlay or opening a file
 | 
					 | 
				
			||||||
// for writing.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
// The calls to
 | 
					 | 
				
			||||||
// Readdir() and Readdirnames() merge the file os.FileInfo / names from the
 | 
					 | 
				
			||||||
// base and the overlay - for files present in both layers, only those
 | 
					 | 
				
			||||||
// from the overlay will be used.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
// When opening files for writing (Create() / OpenFile() with the right flags)
 | 
					 | 
				
			||||||
// the operations will be done in both layers, starting with the overlay. A
 | 
					 | 
				
			||||||
// successful read in the overlay will move the cursor position in the base layer
 | 
					 | 
				
			||||||
// by the number of bytes read.
 | 
					 | 
				
			||||||
type UnionFile struct {
 | 
					 | 
				
			||||||
	Base   File
 | 
					 | 
				
			||||||
	Layer  File
 | 
					 | 
				
			||||||
	Merger DirsMerger
 | 
					 | 
				
			||||||
	off    int
 | 
					 | 
				
			||||||
	files  []os.FileInfo
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (f *UnionFile) Close() error {
 | 
					 | 
				
			||||||
	// first close base, so we have a newer timestamp in the overlay. If we'd close
 | 
					 | 
				
			||||||
	// the overlay first, we'd get a cacheStale the next time we access this file
 | 
					 | 
				
			||||||
	// -> cache would be useless ;-)
 | 
					 | 
				
			||||||
	if f.Base != nil {
 | 
					 | 
				
			||||||
		f.Base.Close()
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if f.Layer != nil {
 | 
					 | 
				
			||||||
		return f.Layer.Close()
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return BADFD
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (f *UnionFile) Read(s []byte) (int, error) {
 | 
					 | 
				
			||||||
	if f.Layer != nil {
 | 
					 | 
				
			||||||
		n, err := f.Layer.Read(s)
 | 
					 | 
				
			||||||
		if (err == nil || err == io.EOF) && f.Base != nil {
 | 
					 | 
				
			||||||
			// advance the file position also in the base file, the next
 | 
					 | 
				
			||||||
			// call may be a write at this position (or a seek with SEEK_CUR)
 | 
					 | 
				
			||||||
			if _, seekErr := f.Base.Seek(int64(n), os.SEEK_CUR); seekErr != nil {
 | 
					 | 
				
			||||||
				// only overwrite err in case the seek fails: we need to
 | 
					 | 
				
			||||||
				// report an eventual io.EOF to the caller
 | 
					 | 
				
			||||||
				err = seekErr
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		return n, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if f.Base != nil {
 | 
					 | 
				
			||||||
		return f.Base.Read(s)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return 0, BADFD
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (f *UnionFile) ReadAt(s []byte, o int64) (int, error) {
 | 
					 | 
				
			||||||
	if f.Layer != nil {
 | 
					 | 
				
			||||||
		n, err := f.Layer.ReadAt(s, o)
 | 
					 | 
				
			||||||
		if (err == nil || err == io.EOF) && f.Base != nil {
 | 
					 | 
				
			||||||
			_, err = f.Base.Seek(o+int64(n), os.SEEK_SET)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		return n, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if f.Base != nil {
 | 
					 | 
				
			||||||
		return f.Base.ReadAt(s, o)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return 0, BADFD
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (f *UnionFile) Seek(o int64, w int) (pos int64, err error) {
 | 
					 | 
				
			||||||
	if f.Layer != nil {
 | 
					 | 
				
			||||||
		pos, err = f.Layer.Seek(o, w)
 | 
					 | 
				
			||||||
		if (err == nil || err == io.EOF) && f.Base != nil {
 | 
					 | 
				
			||||||
			_, err = f.Base.Seek(o, w)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		return pos, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if f.Base != nil {
 | 
					 | 
				
			||||||
		return f.Base.Seek(o, w)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return 0, BADFD
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (f *UnionFile) Write(s []byte) (n int, err error) {
 | 
					 | 
				
			||||||
	if f.Layer != nil {
 | 
					 | 
				
			||||||
		n, err = f.Layer.Write(s)
 | 
					 | 
				
			||||||
		if err == nil && f.Base != nil { // hmm, do we have fixed size files where a write may hit the EOF mark?
 | 
					 | 
				
			||||||
			_, err = f.Base.Write(s)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		return n, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if f.Base != nil {
 | 
					 | 
				
			||||||
		return f.Base.Write(s)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return 0, BADFD
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (f *UnionFile) WriteAt(s []byte, o int64) (n int, err error) {
 | 
					 | 
				
			||||||
	if f.Layer != nil {
 | 
					 | 
				
			||||||
		n, err = f.Layer.WriteAt(s, o)
 | 
					 | 
				
			||||||
		if err == nil && f.Base != nil {
 | 
					 | 
				
			||||||
			_, err = f.Base.WriteAt(s, o)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		return n, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if f.Base != nil {
 | 
					 | 
				
			||||||
		return f.Base.WriteAt(s, o)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return 0, BADFD
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (f *UnionFile) Name() string {
 | 
					 | 
				
			||||||
	if f.Layer != nil {
 | 
					 | 
				
			||||||
		return f.Layer.Name()
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return f.Base.Name()
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// DirsMerger is how UnionFile weaves two directories together.
 | 
					 | 
				
			||||||
// It takes the FileInfo slices from the layer and the base and returns a
 | 
					 | 
				
			||||||
// single view.
 | 
					 | 
				
			||||||
type DirsMerger func(lofi, bofi []os.FileInfo) ([]os.FileInfo, error)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var defaultUnionMergeDirsFn = func(lofi, bofi []os.FileInfo) ([]os.FileInfo, error) {
 | 
					 | 
				
			||||||
	var files = make(map[string]os.FileInfo)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	for _, fi := range lofi {
 | 
					 | 
				
			||||||
		files[fi.Name()] = fi
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	for _, fi := range bofi {
 | 
					 | 
				
			||||||
		if _, exists := files[fi.Name()]; !exists {
 | 
					 | 
				
			||||||
			files[fi.Name()] = fi
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	rfi := make([]os.FileInfo, len(files))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	i := 0
 | 
					 | 
				
			||||||
	for _, fi := range files {
 | 
					 | 
				
			||||||
		rfi[i] = fi
 | 
					 | 
				
			||||||
		i++
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return rfi, nil
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Readdir will weave the two directories together and
 | 
					 | 
				
			||||||
// return a single view of the overlayed directories.
 | 
					 | 
				
			||||||
// At the end of the directory view, the error is io.EOF if c > 0.
 | 
					 | 
				
			||||||
func (f *UnionFile) Readdir(c int) (ofi []os.FileInfo, err error) {
 | 
					 | 
				
			||||||
	var merge DirsMerger = f.Merger
 | 
					 | 
				
			||||||
	if merge == nil {
 | 
					 | 
				
			||||||
		merge = defaultUnionMergeDirsFn
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if f.off == 0 {
 | 
					 | 
				
			||||||
		var lfi []os.FileInfo
 | 
					 | 
				
			||||||
		if f.Layer != nil {
 | 
					 | 
				
			||||||
			lfi, err = f.Layer.Readdir(-1)
 | 
					 | 
				
			||||||
			if err != nil {
 | 
					 | 
				
			||||||
				return nil, err
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		var bfi []os.FileInfo
 | 
					 | 
				
			||||||
		if f.Base != nil {
 | 
					 | 
				
			||||||
			bfi, err = f.Base.Readdir(-1)
 | 
					 | 
				
			||||||
			if err != nil {
 | 
					 | 
				
			||||||
				return nil, err
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		merged, err := merge(lfi, bfi)
 | 
					 | 
				
			||||||
		if err != nil {
 | 
					 | 
				
			||||||
			return nil, err
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		f.files = append(f.files, merged...)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if c <= 0 && len(f.files) == 0 {
 | 
					 | 
				
			||||||
		return f.files, nil
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if f.off >= len(f.files) {
 | 
					 | 
				
			||||||
		return nil, io.EOF
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if c <= 0 {
 | 
					 | 
				
			||||||
		return f.files[f.off:], nil
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if c > len(f.files) {
 | 
					 | 
				
			||||||
		c = len(f.files)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	defer func() { f.off += c }()
 | 
					 | 
				
			||||||
	return f.files[f.off:c], nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (f *UnionFile) Readdirnames(c int) ([]string, error) {
 | 
					 | 
				
			||||||
	rfi, err := f.Readdir(c)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return nil, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	var names []string
 | 
					 | 
				
			||||||
	for _, fi := range rfi {
 | 
					 | 
				
			||||||
		names = append(names, fi.Name())
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return names, nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (f *UnionFile) Stat() (os.FileInfo, error) {
 | 
					 | 
				
			||||||
	if f.Layer != nil {
 | 
					 | 
				
			||||||
		return f.Layer.Stat()
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if f.Base != nil {
 | 
					 | 
				
			||||||
		return f.Base.Stat()
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return nil, BADFD
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (f *UnionFile) Sync() (err error) {
 | 
					 | 
				
			||||||
	if f.Layer != nil {
 | 
					 | 
				
			||||||
		err = f.Layer.Sync()
 | 
					 | 
				
			||||||
		if err == nil && f.Base != nil {
 | 
					 | 
				
			||||||
			err = f.Base.Sync()
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		return err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if f.Base != nil {
 | 
					 | 
				
			||||||
		return f.Base.Sync()
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return BADFD
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (f *UnionFile) Truncate(s int64) (err error) {
 | 
					 | 
				
			||||||
	if f.Layer != nil {
 | 
					 | 
				
			||||||
		err = f.Layer.Truncate(s)
 | 
					 | 
				
			||||||
		if err == nil && f.Base != nil {
 | 
					 | 
				
			||||||
			err = f.Base.Truncate(s)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		return err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if f.Base != nil {
 | 
					 | 
				
			||||||
		return f.Base.Truncate(s)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return BADFD
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (f *UnionFile) WriteString(s string) (n int, err error) {
 | 
					 | 
				
			||||||
	if f.Layer != nil {
 | 
					 | 
				
			||||||
		n, err = f.Layer.WriteString(s)
 | 
					 | 
				
			||||||
		if err == nil && f.Base != nil {
 | 
					 | 
				
			||||||
			_, err = f.Base.WriteString(s)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		return n, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if f.Base != nil {
 | 
					 | 
				
			||||||
		return f.Base.WriteString(s)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return 0, BADFD
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func copyToLayer(base Fs, layer Fs, name string) error {
 | 
					 | 
				
			||||||
	bfh, err := base.Open(name)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	defer bfh.Close()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// First make sure the directory exists
 | 
					 | 
				
			||||||
	exists, err := Exists(layer, filepath.Dir(name))
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if !exists {
 | 
					 | 
				
			||||||
		err = layer.MkdirAll(filepath.Dir(name), 0777) // FIXME?
 | 
					 | 
				
			||||||
		if err != nil {
 | 
					 | 
				
			||||||
			return err
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Create the file on the overlay
 | 
					 | 
				
			||||||
	lfh, err := layer.Create(name)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	n, err := io.Copy(lfh, bfh)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		// If anything fails, clean up the file
 | 
					 | 
				
			||||||
		layer.Remove(name)
 | 
					 | 
				
			||||||
		lfh.Close()
 | 
					 | 
				
			||||||
		return err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	bfi, err := bfh.Stat()
 | 
					 | 
				
			||||||
	if err != nil || bfi.Size() != n {
 | 
					 | 
				
			||||||
		layer.Remove(name)
 | 
					 | 
				
			||||||
		lfh.Close()
 | 
					 | 
				
			||||||
		return syscall.EIO
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	err = lfh.Close()
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		layer.Remove(name)
 | 
					 | 
				
			||||||
		lfh.Close()
 | 
					 | 
				
			||||||
		return err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return layer.Chtimes(name, bfi.ModTime(), bfi.ModTime())
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										330
									
								
								vendor/github.com/spf13/afero/util.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										330
									
								
								vendor/github.com/spf13/afero/util.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,330 +0,0 @@
 | 
				
			|||||||
// Copyright ©2015 Steve Francia <spf@spf13.com>
 | 
					 | 
				
			||||||
// Portions Copyright ©2015 The Hugo Authors
 | 
					 | 
				
			||||||
// Portions Copyright 2016-present Bjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
// 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.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
package afero
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"bytes"
 | 
					 | 
				
			||||||
	"fmt"
 | 
					 | 
				
			||||||
	"io"
 | 
					 | 
				
			||||||
	"os"
 | 
					 | 
				
			||||||
	"path/filepath"
 | 
					 | 
				
			||||||
	"strings"
 | 
					 | 
				
			||||||
	"unicode"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	"golang.org/x/text/transform"
 | 
					 | 
				
			||||||
	"golang.org/x/text/unicode/norm"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Filepath separator defined by os.Separator.
 | 
					 | 
				
			||||||
const FilePathSeparator = string(filepath.Separator)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Takes a reader and a path and writes the content
 | 
					 | 
				
			||||||
func (a Afero) WriteReader(path string, r io.Reader) (err error) {
 | 
					 | 
				
			||||||
	return WriteReader(a.Fs, path, r)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func WriteReader(fs Fs, path string, r io.Reader) (err error) {
 | 
					 | 
				
			||||||
	dir, _ := filepath.Split(path)
 | 
					 | 
				
			||||||
	ospath := filepath.FromSlash(dir)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if ospath != "" {
 | 
					 | 
				
			||||||
		err = fs.MkdirAll(ospath, 0777) // rwx, rw, r
 | 
					 | 
				
			||||||
		if err != nil {
 | 
					 | 
				
			||||||
			if err != os.ErrExist {
 | 
					 | 
				
			||||||
				return err
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	file, err := fs.Create(path)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	defer file.Close()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	_, err = io.Copy(file, r)
 | 
					 | 
				
			||||||
	return
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Same as WriteReader but checks to see if file/directory already exists.
 | 
					 | 
				
			||||||
func (a Afero) SafeWriteReader(path string, r io.Reader) (err error) {
 | 
					 | 
				
			||||||
	return SafeWriteReader(a.Fs, path, r)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func SafeWriteReader(fs Fs, path string, r io.Reader) (err error) {
 | 
					 | 
				
			||||||
	dir, _ := filepath.Split(path)
 | 
					 | 
				
			||||||
	ospath := filepath.FromSlash(dir)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if ospath != "" {
 | 
					 | 
				
			||||||
		err = fs.MkdirAll(ospath, 0777) // rwx, rw, r
 | 
					 | 
				
			||||||
		if err != nil {
 | 
					 | 
				
			||||||
			return
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	exists, err := Exists(fs, path)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if exists {
 | 
					 | 
				
			||||||
		return fmt.Errorf("%v already exists", path)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	file, err := fs.Create(path)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	defer file.Close()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	_, err = io.Copy(file, r)
 | 
					 | 
				
			||||||
	return
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (a Afero) GetTempDir(subPath string) string {
 | 
					 | 
				
			||||||
	return GetTempDir(a.Fs, subPath)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// GetTempDir returns the default temp directory with trailing slash
 | 
					 | 
				
			||||||
// if subPath is not empty then it will be created recursively with mode 777 rwx rwx rwx
 | 
					 | 
				
			||||||
func GetTempDir(fs Fs, subPath string) string {
 | 
					 | 
				
			||||||
	addSlash := func(p string) string {
 | 
					 | 
				
			||||||
		if FilePathSeparator != p[len(p)-1:] {
 | 
					 | 
				
			||||||
			p = p + FilePathSeparator
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		return p
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	dir := addSlash(os.TempDir())
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if subPath != "" {
 | 
					 | 
				
			||||||
		// preserve windows backslash :-(
 | 
					 | 
				
			||||||
		if FilePathSeparator == "\\" {
 | 
					 | 
				
			||||||
			subPath = strings.Replace(subPath, "\\", "____", -1)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		dir = dir + UnicodeSanitize((subPath))
 | 
					 | 
				
			||||||
		if FilePathSeparator == "\\" {
 | 
					 | 
				
			||||||
			dir = strings.Replace(dir, "____", "\\", -1)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if exists, _ := Exists(fs, dir); exists {
 | 
					 | 
				
			||||||
			return addSlash(dir)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		err := fs.MkdirAll(dir, 0777)
 | 
					 | 
				
			||||||
		if err != nil {
 | 
					 | 
				
			||||||
			panic(err)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		dir = addSlash(dir)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return dir
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Rewrite string to remove non-standard path characters
 | 
					 | 
				
			||||||
func UnicodeSanitize(s string) string {
 | 
					 | 
				
			||||||
	source := []rune(s)
 | 
					 | 
				
			||||||
	target := make([]rune, 0, len(source))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	for _, r := range source {
 | 
					 | 
				
			||||||
		if unicode.IsLetter(r) ||
 | 
					 | 
				
			||||||
			unicode.IsDigit(r) ||
 | 
					 | 
				
			||||||
			unicode.IsMark(r) ||
 | 
					 | 
				
			||||||
			r == '.' ||
 | 
					 | 
				
			||||||
			r == '/' ||
 | 
					 | 
				
			||||||
			r == '\\' ||
 | 
					 | 
				
			||||||
			r == '_' ||
 | 
					 | 
				
			||||||
			r == '-' ||
 | 
					 | 
				
			||||||
			r == '%' ||
 | 
					 | 
				
			||||||
			r == ' ' ||
 | 
					 | 
				
			||||||
			r == '#' {
 | 
					 | 
				
			||||||
			target = append(target, r)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return string(target)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Transform characters with accents into plain forms.
 | 
					 | 
				
			||||||
func NeuterAccents(s string) string {
 | 
					 | 
				
			||||||
	t := transform.Chain(norm.NFD, transform.RemoveFunc(isMn), norm.NFC)
 | 
					 | 
				
			||||||
	result, _, _ := transform.String(t, string(s))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return result
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func isMn(r rune) bool {
 | 
					 | 
				
			||||||
	return unicode.Is(unicode.Mn, r) // Mn: nonspacing marks
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (a Afero) FileContainsBytes(filename string, subslice []byte) (bool, error) {
 | 
					 | 
				
			||||||
	return FileContainsBytes(a.Fs, filename, subslice)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Check if a file contains a specified byte slice.
 | 
					 | 
				
			||||||
func FileContainsBytes(fs Fs, filename string, subslice []byte) (bool, error) {
 | 
					 | 
				
			||||||
	f, err := fs.Open(filename)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return false, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	defer f.Close()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return readerContainsAny(f, subslice), nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (a Afero) FileContainsAnyBytes(filename string, subslices [][]byte) (bool, error) {
 | 
					 | 
				
			||||||
	return FileContainsAnyBytes(a.Fs, filename, subslices)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Check if a file contains any of the specified byte slices.
 | 
					 | 
				
			||||||
func FileContainsAnyBytes(fs Fs, filename string, subslices [][]byte) (bool, error) {
 | 
					 | 
				
			||||||
	f, err := fs.Open(filename)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return false, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	defer f.Close()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return readerContainsAny(f, subslices...), nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// readerContains reports whether any of the subslices is within r.
 | 
					 | 
				
			||||||
func readerContainsAny(r io.Reader, subslices ...[]byte) bool {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if r == nil || len(subslices) == 0 {
 | 
					 | 
				
			||||||
		return false
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	largestSlice := 0
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	for _, sl := range subslices {
 | 
					 | 
				
			||||||
		if len(sl) > largestSlice {
 | 
					 | 
				
			||||||
			largestSlice = len(sl)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if largestSlice == 0 {
 | 
					 | 
				
			||||||
		return false
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	bufflen := largestSlice * 4
 | 
					 | 
				
			||||||
	halflen := bufflen / 2
 | 
					 | 
				
			||||||
	buff := make([]byte, bufflen)
 | 
					 | 
				
			||||||
	var err error
 | 
					 | 
				
			||||||
	var n, i int
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	for {
 | 
					 | 
				
			||||||
		i++
 | 
					 | 
				
			||||||
		if i == 1 {
 | 
					 | 
				
			||||||
			n, err = io.ReadAtLeast(r, buff[:halflen], halflen)
 | 
					 | 
				
			||||||
		} else {
 | 
					 | 
				
			||||||
			if i != 2 {
 | 
					 | 
				
			||||||
				// shift left to catch overlapping matches
 | 
					 | 
				
			||||||
				copy(buff[:], buff[halflen:])
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			n, err = io.ReadAtLeast(r, buff[halflen:], halflen)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if n > 0 {
 | 
					 | 
				
			||||||
			for _, sl := range subslices {
 | 
					 | 
				
			||||||
				if bytes.Contains(buff, sl) {
 | 
					 | 
				
			||||||
					return true
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if err != nil {
 | 
					 | 
				
			||||||
			break
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return false
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (a Afero) DirExists(path string) (bool, error) {
 | 
					 | 
				
			||||||
	return DirExists(a.Fs, path)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// DirExists checks if a path exists and is a directory.
 | 
					 | 
				
			||||||
func DirExists(fs Fs, path string) (bool, error) {
 | 
					 | 
				
			||||||
	fi, err := fs.Stat(path)
 | 
					 | 
				
			||||||
	if err == nil && fi.IsDir() {
 | 
					 | 
				
			||||||
		return true, nil
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if os.IsNotExist(err) {
 | 
					 | 
				
			||||||
		return false, nil
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return false, err
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (a Afero) IsDir(path string) (bool, error) {
 | 
					 | 
				
			||||||
	return IsDir(a.Fs, path)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// IsDir checks if a given path is a directory.
 | 
					 | 
				
			||||||
func IsDir(fs Fs, path string) (bool, error) {
 | 
					 | 
				
			||||||
	fi, err := fs.Stat(path)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return false, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return fi.IsDir(), nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (a Afero) IsEmpty(path string) (bool, error) {
 | 
					 | 
				
			||||||
	return IsEmpty(a.Fs, path)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// IsEmpty checks if a given file or directory is empty.
 | 
					 | 
				
			||||||
func IsEmpty(fs Fs, path string) (bool, error) {
 | 
					 | 
				
			||||||
	if b, _ := Exists(fs, path); !b {
 | 
					 | 
				
			||||||
		return false, fmt.Errorf("%q path does not exist", path)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	fi, err := fs.Stat(path)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return false, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if fi.IsDir() {
 | 
					 | 
				
			||||||
		f, err := fs.Open(path)
 | 
					 | 
				
			||||||
		if err != nil {
 | 
					 | 
				
			||||||
			return false, err
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		defer f.Close()
 | 
					 | 
				
			||||||
		list, err := f.Readdir(-1)
 | 
					 | 
				
			||||||
		return len(list) == 0, nil
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return fi.Size() == 0, nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (a Afero) Exists(path string) (bool, error) {
 | 
					 | 
				
			||||||
	return Exists(a.Fs, path)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Check if a file or directory exists.
 | 
					 | 
				
			||||||
func Exists(fs Fs, path string) (bool, error) {
 | 
					 | 
				
			||||||
	_, err := fs.Stat(path)
 | 
					 | 
				
			||||||
	if err == nil {
 | 
					 | 
				
			||||||
		return true, nil
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if os.IsNotExist(err) {
 | 
					 | 
				
			||||||
		return false, nil
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return false, err
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func FullBaseFsPath(basePathFs *BasePathFs, relativePath string) string {
 | 
					 | 
				
			||||||
	combinedPath := filepath.Join(basePathFs.path, relativePath)
 | 
					 | 
				
			||||||
	if parent, ok := basePathFs.source.(*BasePathFs); ok {
 | 
					 | 
				
			||||||
		return FullBaseFsPath(parent, combinedPath)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return combinedPath
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										4
									
								
								vendor/modules.txt
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								vendor/modules.txt
									
									
									
									
										vendored
									
									
								
							@@ -706,10 +706,6 @@ github.com/shurcooL/sanitized_anchor_name
 | 
				
			|||||||
github.com/sirupsen/logrus
 | 
					github.com/sirupsen/logrus
 | 
				
			||||||
# github.com/soheilhy/cmux v0.1.5 => github.com/soheilhy/cmux v0.1.5
 | 
					# github.com/soheilhy/cmux v0.1.5 => github.com/soheilhy/cmux v0.1.5
 | 
				
			||||||
github.com/soheilhy/cmux
 | 
					github.com/soheilhy/cmux
 | 
				
			||||||
# github.com/spf13/afero v1.2.2 => github.com/spf13/afero v1.2.2
 | 
					 | 
				
			||||||
## explicit
 | 
					 | 
				
			||||||
github.com/spf13/afero
 | 
					 | 
				
			||||||
github.com/spf13/afero/mem
 | 
					 | 
				
			||||||
# github.com/spf13/cobra v1.1.3 => github.com/spf13/cobra v1.1.3
 | 
					# github.com/spf13/cobra v1.1.3 => github.com/spf13/cobra v1.1.3
 | 
				
			||||||
## explicit
 | 
					## explicit
 | 
				
			||||||
github.com/spf13/cobra
 | 
					github.com/spf13/cobra
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user