github.com/SuCicada/su-hugo@v1.0.0/hugofs/glob.go (about)

     1  // Copyright 2019 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  	"errors"
    18  	"path/filepath"
    19  	"strings"
    20  
    21  	"github.com/gohugoio/hugo/hugofs/glob"
    22  
    23  	"github.com/spf13/afero"
    24  )
    25  
    26  // Glob walks the fs and passes all matches to the handle func.
    27  // The handle func can return true to signal a stop.
    28  func Glob(fs afero.Fs, pattern string, handle func(fi FileMetaInfo) (bool, error)) error {
    29  	pattern = glob.NormalizePathNoLower(pattern)
    30  	if pattern == "" {
    31  		return nil
    32  	}
    33  	root := glob.ResolveRootDir(pattern)
    34  	pattern = strings.ToLower(pattern)
    35  
    36  	g, err := glob.GetGlob(pattern)
    37  	if err != nil {
    38  		return err
    39  	}
    40  
    41  	hasSuperAsterisk := strings.Contains(pattern, "**")
    42  	levels := strings.Count(pattern, "/")
    43  
    44  	// Signals that we're done.
    45  	done := errors.New("done")
    46  
    47  	wfn := func(p string, info FileMetaInfo, err error) error {
    48  		p = glob.NormalizePath(p)
    49  		if info.IsDir() {
    50  			if !hasSuperAsterisk {
    51  				// Avoid walking to the bottom if we can avoid it.
    52  				if p != "" && strings.Count(p, "/") >= levels {
    53  					return filepath.SkipDir
    54  				}
    55  			}
    56  			return nil
    57  		}
    58  
    59  		if g.Match(p) {
    60  			d, err := handle(info)
    61  			if err != nil {
    62  				return err
    63  			}
    64  			if d {
    65  				return done
    66  			}
    67  		}
    68  
    69  		return nil
    70  	}
    71  
    72  	w := NewWalkway(WalkwayConfig{
    73  		Root:   root,
    74  		Fs:     fs,
    75  		WalkFn: wfn,
    76  	})
    77  
    78  	err = w.Walk()
    79  
    80  	if err != done {
    81  		return err
    82  	}
    83  
    84  	return nil
    85  }