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