| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146 |
- /*
- Copyright 2020 Docker Compose CLI 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 watch
- import (
- "fmt"
- "os"
- "path/filepath"
- "strings"
- "github.com/moby/buildkit/frontend/dockerfile/dockerignore"
- "github.com/moby/patternmatcher"
- )
- type dockerPathMatcher struct {
- repoRoot string
- matcher *patternmatcher.PatternMatcher
- }
- func (i dockerPathMatcher) Matches(f string) (bool, error) {
- if !filepath.IsAbs(f) {
- f = filepath.Join(i.repoRoot, f)
- }
- return i.matcher.MatchesOrParentMatches(f)
- }
- func (i dockerPathMatcher) MatchesEntireDir(f string) (bool, error) {
- matches, err := i.Matches(f)
- if !matches || err != nil {
- return matches, err
- }
- // We match the dir, but we might exclude files underneath it.
- if i.matcher.Exclusions() {
- for _, pattern := range i.matcher.Patterns() {
- if !pattern.Exclusion() {
- continue
- }
- if IsChild(f, pattern.String()) {
- // Found an exclusion match -- we don't match this whole dir
- return false, nil
- }
- }
- return true, nil
- }
- return true, nil
- }
- func LoadDockerIgnore(repoRoot string) (*dockerPathMatcher, error) {
- absRoot, err := filepath.Abs(repoRoot)
- if err != nil {
- return nil, err
- }
- patterns, err := readDockerignorePatterns(absRoot)
- if err != nil {
- return nil, err
- }
- return NewDockerPatternMatcher(absRoot, patterns)
- }
- // Make all the patterns use absolute paths.
- func absPatterns(absRoot string, patterns []string) []string {
- absPatterns := make([]string, 0, len(patterns))
- for _, p := range patterns {
- // The pattern parsing here is loosely adapted from fileutils' NewPatternMatcher
- p = strings.TrimSpace(p)
- if p == "" {
- continue
- }
- p = filepath.Clean(p)
- pPath := p
- isExclusion := false
- if p[0] == '!' {
- pPath = p[1:]
- isExclusion = true
- }
- if !filepath.IsAbs(pPath) {
- pPath = filepath.Join(absRoot, pPath)
- }
- absPattern := pPath
- if isExclusion {
- absPattern = fmt.Sprintf("!%s", pPath)
- }
- absPatterns = append(absPatterns, absPattern)
- }
- return absPatterns
- }
- func NewDockerPatternMatcher(repoRoot string, patterns []string) (*dockerPathMatcher, error) {
- absRoot, err := filepath.Abs(repoRoot)
- if err != nil {
- return nil, err
- }
- pm, err := patternmatcher.New(absPatterns(absRoot, patterns))
- if err != nil {
- return nil, err
- }
- return &dockerPathMatcher{
- repoRoot: absRoot,
- matcher: pm,
- }, nil
- }
- func readDockerignorePatterns(repoRoot string) ([]string, error) {
- var excludes []string
- f, err := os.Open(filepath.Join(repoRoot, ".dockerignore"))
- switch {
- case os.IsNotExist(err):
- return excludes, nil
- case err != nil:
- return nil, err
- }
- defer func() { _ = f.Close() }()
- return dockerignore.ReadAll(f)
- }
- func DockerIgnoreTesterFromContents(repoRoot string, contents string) (*dockerPathMatcher, error) {
- patterns, err := dockerignore.ReadAll(strings.NewReader(contents))
- if err != nil {
- return nil, err
- }
- return NewDockerPatternMatcher(repoRoot, patterns)
- }
|