#!/usr/bin/ruby -w # -*- ruby -*- require './regexp' require './log' # Represents .p4ignore files, which are modeled on .cvsignore files. class IgnoredPatterns < Hash include Log def initialize(ignorename) @ignorename = ignorename @dirsread = Array.new end def read(dir) # from the CVS default settings -- ignoring overrides log "reading ignored patterns for " + dir return if @dirsread.include?(dir) @dirsread.push(dir) pats = %w{ CVS *~ .p4ignore .p4config *.o *$ *.BAK *.Z *.a *.bak *.elc *.exe *.ln *.obj *.olb *.old *.orig *.rej *.so . .. .del-* .make.state .nse_depinfo CVS.adm RCS RCSLOG SCCS TAGS _$* core cvslog.* tags } # can't put these guys in the qw() list: ['.#*', '#*', ',*'].each { |p| pats.push(p) } # read ~/ homedir = ENV["HOME"] # unix unless homedir # windows homedir = ENV["HOMEDRIVE"] homepath = ENV["HOMEPATH"] if homepath then if homedir then homedir += homepath else homedir = homepath end end end global = read_ignore_file(homedir) pats.push(*global) unless global.length == 0 # read in the current directory local = read_ignore_file(dir) pats.push(*local) unless local.length == 0 # prepend the current directory to the patterns, contending with the fact # that the directory might actually be a valid regular expression. # wildcard if the pattern is a directory pats = pats.collect do |p| p += "/*" if File.directory?(dir + "/" + p) p end qdir = Regexp.quote(dir) pats = pats.collect do |p| p = Regexp.unixre_to_string(p) qdir + "/" + p end # make a regular expression for each one, to be the entire string (^...$) self[dir] = Array.new pats.each do |p| re = Regexp.new("^" + p + "$") # log "IgnoredPatterns: storing re " + re.source + " for dir " + dir self[dir].push(re) end end def read_ignore_file(dir) pats = Array.new if dir then cifile = dir + "/" + @ignorename if File.exists?(cifile) IO.foreach(cifile) do |line| line.chomp! line.gsub!(/\+/, '\\+') pats.push(*line.split) end else log "no ignore file in " + dir end end pats end # Returns if the file is ignored. Checks the name as both "./name" and "name". def is_ignored?(name) log "is_ignored?(" + name + ")" if name.index("./") == 0 withpref, nopref = name, name.sub!("./", "") else withpref, nopref = "./" + name, name end [ withpref, nopref ].each do |name| dir = name log "dirs = " + keys.join(", ") while dir = File.dirname(dir) if include?(dir) regexps = self[dir] regexps.each do |re| # log "matching " + name + " against " + re.source # stop as soon as we find out it is ignored return true if re.match(name) end else log "dir " + dir + " is not included" end break if dir == "." # else we'll cycle continuously end end return false # it's not ignored end end