github.com/stackb/hugo@v0.47.1/hugofs/basepath_real_filename_fs.go (about)

     1  // Copyright 2018 The Hugo Authors. All rights reserved.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  // http://www.apache.org/licenses/LICENSE-2.0
     7  //
     8  // Unless required by applicable law or agreed to in writing, software
     9  // distributed under the License is distributed on an "AS IS" BASIS,
    10  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    11  // See the License for the specific language governing permissions and
    12  // limitations under the License.
    13  
    14  package hugofs
    15  
    16  import (
    17  	"os"
    18  
    19  	"github.com/spf13/afero"
    20  )
    21  
    22  // RealFilenameInfo is a thin wrapper around os.FileInfo adding the real filename.
    23  type RealFilenameInfo interface {
    24  	os.FileInfo
    25  
    26  	// This is the real filename to the file in the underlying filesystem.
    27  	RealFilename() string
    28  }
    29  
    30  type realFilenameInfo struct {
    31  	os.FileInfo
    32  	realFilename string
    33  }
    34  
    35  func (f *realFilenameInfo) RealFilename() string {
    36  	return f.realFilename
    37  }
    38  
    39  func NewBasePathRealFilenameFs(base *afero.BasePathFs) *BasePathRealFilenameFs {
    40  	return &BasePathRealFilenameFs{BasePathFs: base}
    41  }
    42  
    43  // This is a thin wrapper around afero.BasePathFs that provides the real filename
    44  // in Stat and LstatIfPossible.
    45  type BasePathRealFilenameFs struct {
    46  	*afero.BasePathFs
    47  }
    48  
    49  func (b *BasePathRealFilenameFs) Stat(name string) (os.FileInfo, error) {
    50  	fi, err := b.BasePathFs.Stat(name)
    51  	if err != nil {
    52  		return nil, err
    53  	}
    54  
    55  	if _, ok := fi.(RealFilenameInfo); ok {
    56  		return fi, nil
    57  	}
    58  
    59  	filename, err := b.RealPath(name)
    60  	if err != nil {
    61  		return nil, &os.PathError{Op: "stat", Path: name, Err: err}
    62  	}
    63  
    64  	return &realFilenameInfo{FileInfo: fi, realFilename: filename}, nil
    65  }
    66  
    67  func (b *BasePathRealFilenameFs) LstatIfPossible(name string) (os.FileInfo, bool, error) {
    68  
    69  	fi, ok, err := b.BasePathFs.LstatIfPossible(name)
    70  	if err != nil {
    71  		return nil, false, err
    72  	}
    73  
    74  	if _, ok := fi.(RealFilenameInfo); ok {
    75  		return fi, ok, nil
    76  	}
    77  
    78  	filename, err := b.RealPath(name)
    79  	if err != nil {
    80  		return nil, false, &os.PathError{Op: "lstat", Path: name, Err: err}
    81  	}
    82  
    83  	return &realFilenameInfo{FileInfo: fi, realFilename: filename}, ok, nil
    84  }