github.com/git-ogawa/go-dbyml@v1.2.1/dbyml/dockerignore.go (about)

     1  package dbyml
     2  
     3  import (
     4  	"bufio"
     5  	"bytes"
     6  	"fmt"
     7  	"io"
     8  	"io/fs"
     9  	"os"
    10  	"path"
    11  	"path/filepath"
    12  	"strings"
    13  )
    14  
    15  // ReadDockerignore reads exclude files from .dockerignore.
    16  // If not exists, return empty list.
    17  func ReadDockerignore(dir string) ([]string, error) {
    18  	excludes := []string{}
    19  	reader, err := SearchDockerignore(dir)
    20  	if err != nil {
    21  		return nil, err
    22  	}
    23  
    24  	if reader != nil {
    25  		exclude, err := ReadAll(reader)
    26  		if err != nil {
    27  			return excludes, err
    28  		}
    29  		excludes = append(excludes, exclude...)
    30  	}
    31  	return excludes, nil
    32  }
    33  
    34  // SearchDockerignore searches .dockerignore exists in a given directory.
    35  // If exists, return the io.Reader of the .dockerignore, otherwise return nil.
    36  func SearchDockerignore(dir string) (io.Reader, error) {
    37  	var ignore string
    38  	if err := filepath.Walk(dir, func(file string, info fs.FileInfo, err error) error {
    39  		if path.Base(file) == ".dockerignore" {
    40  			ignore = file
    41  		}
    42  		return nil
    43  	}); err != nil {
    44  		return nil, err
    45  	}
    46  
    47  	if ignore == "" {
    48  		return nil, nil
    49  	}
    50  
    51  	f, err := os.Open(ignore)
    52  	return f, err
    53  }
    54  
    55  // ReadAll reads a .dockerignore file and returns the list of file patterns
    56  // to ignore. Note this will trim whitespace from each line as well
    57  // as use GO's "clean" func to get the shortest/cleanest path for each.
    58  func ReadAll(reader io.Reader) ([]string, error) {
    59  	if reader == nil {
    60  		return nil, nil
    61  	}
    62  
    63  	scanner := bufio.NewScanner(reader)
    64  	var excludes []string
    65  	currentLine := 0
    66  
    67  	utf8bom := []byte{0xEF, 0xBB, 0xBF}
    68  	for scanner.Scan() {
    69  		scannedBytes := scanner.Bytes()
    70  		// We trim UTF8 BuildkitdTomlTemplate
    71  		if currentLine == 0 {
    72  			scannedBytes = bytes.TrimPrefix(scannedBytes, utf8bom)
    73  		}
    74  		pattern := string(scannedBytes)
    75  		currentLine++
    76  		// Lines starting with # (comments) are ignored before processing
    77  		if strings.HasPrefix(pattern, "#") {
    78  			continue
    79  		}
    80  		pattern = strings.TrimSpace(pattern)
    81  		if pattern == "" {
    82  			continue
    83  		}
    84  		// normalize absolute paths to paths relative to the context
    85  		// (taking care of '!' prefix)
    86  		invert := pattern[0] == '!'
    87  		if invert {
    88  			pattern = strings.TrimSpace(pattern[1:])
    89  		}
    90  		if len(pattern) > 0 {
    91  			pattern = filepath.Clean(pattern)
    92  			pattern = filepath.ToSlash(pattern)
    93  			if len(pattern) > 1 && pattern[0] == '/' {
    94  				pattern = pattern[1:]
    95  			}
    96  		}
    97  		if invert {
    98  			pattern = "!" + pattern
    99  		}
   100  
   101  		excludes = append(excludes, pattern)
   102  	}
   103  	if err := scanner.Err(); err != nil {
   104  		return nil, fmt.Errorf("Error reading .dockerignore: %v", err)
   105  	}
   106  	return excludes, nil
   107  }