github.com/kubesphere/s2irun@v3.2.1+incompatible/pkg/ignore/ignore.go (about)

     1  package ignore
     2  
     3  import (
     4  	"bufio"
     5  	"io"
     6  	"os"
     7  	"path/filepath"
     8  	"strings"
     9  
    10  	"github.com/kubesphere/s2irun/pkg/api"
    11  	"github.com/kubesphere/s2irun/pkg/api/constants"
    12  	utilglog "github.com/kubesphere/s2irun/pkg/utils/glog"
    13  )
    14  
    15  var glog = utilglog.StderrLog
    16  
    17  // DockerIgnorer ignores files based on the contents of the .s2iignore file
    18  type DockerIgnorer struct{}
    19  
    20  // Ignore removes files from the workspace based on the contents of the
    21  // .s2iignore file
    22  func (b *DockerIgnorer) Ignore(config *api.Config) error {
    23  	/*
    24  		 so, to duplicate the .dockerignore capabilities (https://docs.docker.com/reference/builder/#dockerignore-file)
    25  		 we have a flow that follows:
    26  		0) First note, .dockerignore rules are NOT recursive (unlike .gitignore) .. you have to list subdir explicitly
    27  		1) Read in the exclusion patterns
    28  		2) Skip over comments (noted by #)
    29  		3) note overrides (via exclamation sign i.e. !) and reinstate files (don't remove) as needed
    30  		4) leverage Glob matching to build list, as .dockerignore is documented as following filepath.Match / filepath.Glob
    31  		5) del files
    32  		 1 to 4 is in getListOfFilesToIgnore
    33  	*/
    34  	filesToDel, lerr := getListOfFilesToIgnore(config.WorkingSourceDir)
    35  	if lerr != nil {
    36  		return lerr
    37  	}
    38  
    39  	if filesToDel == nil {
    40  		return nil
    41  	}
    42  
    43  	// delete compiled list of files
    44  	for _, fileToDel := range filesToDel {
    45  		glog.V(5).Infof("attempting to remove file %s \n", fileToDel)
    46  		rerr := os.RemoveAll(fileToDel)
    47  		if rerr != nil {
    48  			glog.Errorf("error removing file %s because of %v \n", fileToDel, rerr)
    49  			return rerr
    50  		}
    51  	}
    52  
    53  	return nil
    54  }
    55  
    56  func getListOfFilesToIgnore(workingDir string) (map[string]string, error) {
    57  	path := filepath.Join(workingDir, constants.IgnoreFile)
    58  	file, err := os.Open(path)
    59  	if err != nil {
    60  		if !os.IsNotExist(err) {
    61  			glog.Errorf("Ignore processing, problem opening %s because of %v\n", path, err)
    62  			return nil, err
    63  		}
    64  		glog.V(4).Info(".s2iignore file does not exist")
    65  		return nil, nil
    66  	}
    67  	defer file.Close()
    68  
    69  	filesToDel := make(map[string]string)
    70  	scanner := bufio.NewScanner(file)
    71  	for scanner.Scan() {
    72  		filespec := strings.Trim(scanner.Text(), " ")
    73  
    74  		if len(filespec) == 0 {
    75  			continue
    76  		}
    77  
    78  		if strings.HasPrefix(filespec, "#") {
    79  			continue
    80  		}
    81  
    82  		glog.V(4).Infof(".s2iignore lists a file spec of %s \n", filespec)
    83  
    84  		if strings.HasPrefix(filespec, "!") {
    85  			//remove any existing files to del that the override covers
    86  			// and patterns later on that undo this take precedence
    87  
    88  			// first, remove ! ... note, replace ! with */ did not have
    89  			// expected effect with filepath.Match
    90  			filespec = strings.Replace(filespec, "!", "", 1)
    91  
    92  			// iterate through and determine ones to leave in
    93  			dontDel := []string{}
    94  			for candidate := range filesToDel {
    95  				compare := filepath.Join(workingDir, filespec)
    96  				glog.V(5).Infof("For %s  and %s see if it matches the spec  %s which means that we leave in\n", filespec, candidate, compare)
    97  				leaveIn, _ := filepath.Match(compare, candidate)
    98  				if leaveIn {
    99  					glog.V(5).Infof("Not removing %s \n", candidate)
   100  					dontDel = append(dontDel, candidate)
   101  				} else {
   102  					glog.V(5).Infof("No match for %s and %s \n", filespec, candidate)
   103  				}
   104  			}
   105  
   106  			// now remove any matches from files to delete list
   107  			for _, leaveIn := range dontDel {
   108  				delete(filesToDel, leaveIn)
   109  			}
   110  			continue
   111  		}
   112  
   113  		globspec := filepath.Join(workingDir, filespec)
   114  		glog.V(4).Infof("using globspec %s \n", globspec)
   115  		list, gerr := filepath.Glob(globspec)
   116  		if gerr != nil {
   117  			glog.V(4).Infof("Glob failed with %v \n", gerr)
   118  		} else {
   119  			for _, globresult := range list {
   120  				glog.V(5).Infof("Glob result %s \n", globresult)
   121  				filesToDel[globresult] = globresult
   122  
   123  			}
   124  		}
   125  
   126  	}
   127  
   128  	if err := scanner.Err(); err != nil && err != io.EOF {
   129  		glog.Errorf("Problem processing .s2iignore %v \n", err)
   130  		return nil, err
   131  	}
   132  
   133  	return filesToDel, nil
   134  }