Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Handle exclusions when ignoring files #541

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 16 additions & 4 deletions lib/docker/util.rb
Original file line number Diff line number Diff line change
Expand Up @@ -259,7 +259,7 @@ def build_config_header(credentials)
end

def glob_all_files(pattern)
Dir.glob(pattern, File::FNM_DOTMATCH) - ['..', '.']
Dir.glob(pattern, File::FNM_DOTMATCH)
end

def remove_ignored_files!(directory, files)
Expand All @@ -268,11 +268,23 @@ def remove_ignored_files!(directory, files)
ignored_files(directory, ignore).each { |f| files.delete(f) }
end

def ignored_files(directory, ignore_file)
patterns = File.read(ignore_file).split("\n").each(&:strip!)
patterns.reject! { |p| p.empty? || p.start_with?('#') }
def resolve_patterns(patterns, directory)
patterns.map! { |p| File.join(directory, p) }
patterns.map! { |p| File.directory?(p) ? "#{p}/**/*" : p }
patterns.flat_map { |p| p =~ GLOB_WILDCARDS ? glob_all_files(p) : p }
end

def ignored_files(directory, ignore_file)
patterns = File.read(ignore_file).split("\n").each(&:strip!)
patterns.reject! { |p| p.empty? || p.start_with?('#') }

exclusion_patterns = patterns.select { |p| p.start_with?('!') }
inclusion_patterns = patterns - exclusion_patterns
exclusion_patterns.map! { |p| p[1..-1] }.concat(%w(Dockerfile .dockerignore))

files_ignored = resolve_patterns(inclusion_patterns, directory)
files_excluded = resolve_patterns(exclusion_patterns, directory)

files_ignored - files_excluded - [File.join(directory, '.'), File.join(directory, '..')]
end
end
80 changes: 80 additions & 0 deletions spec/docker/util_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,31 @@
expect(files_in_tar(tar)).to eq ['.dockerignore', 'baz']
end

it 'does not ignore files starting with !' do
File.write("#{tmpdir}/Dockerfile", 'bar')

File.write("#{tmpdir}/.dockerignore", '*')

expect(files_in_tar(tar)).to eq ['.dockerignore', 'Dockerfile']
end

it 'does not ignore the Dockerfile' do
File.write("#{tmpdir}/Dockerfile", 'bar')

File.write("#{tmpdir}/.dockerignore", '*')

expect(files_in_tar(tar)).to eq ['.dockerignore', 'Dockerfile']
end

it 'ignores files' do
File.write("#{tmpdir}/foo", 'bar')
File.write("#{tmpdir}/baz", 'bar')

File.write("#{tmpdir}/.dockerignore", "foo")

expect(files_in_tar(tar)).to eq ['.dockerignore', 'baz']
end

it 'ignores folders' do
FileUtils.mkdir("#{tmpdir}/foo")
File.write("#{tmpdir}/foo/bar", 'bar')
Expand Down Expand Up @@ -249,6 +274,61 @@
end
end

describe '.ignored_files' do
attr_accessor :tmpdir

subject do
described_class.ignored_files(tmpdir, ignore_file).map do |f|
f[tmpdir.length+1..-1]
end
end

let(:ignore_file) { "#{tmpdir}/.dockerignore" }

around do |example|
Dir.mktmpdir do |tmpdir|
self.tmpdir = tmpdir
example.call
end
end

it 'ignores explicit files' do
File.write("#{tmpdir}/foo", 'bar')
File.write("#{tmpdir}/baz", 'bar')

File.write("#{tmpdir}/.dockerignore", "foo")

expect(subject).to eq %w(foo)
end

it 'makes an exception to exclusions' do
File.write("#{tmpdir}/foo", 'bar')
File.write("#{tmpdir}/baz", 'bar')

File.write("#{tmpdir}/.dockerignore", "foo\n!foo")

expect(subject).to be_empty
end

it 'makes an exception to exclusions (order doesnt matter)' do
File.write("#{tmpdir}/foo", 'bar')
File.write("#{tmpdir}/baz", 'bar')

File.write("#{tmpdir}/.dockerignore", "!foo\nfoo")

expect(subject).to be_empty
end

it 'does not ignore the Dockerfile or .dockerignore' do
File.write("#{tmpdir}/Dockerfile", 'bar')
File.write("#{tmpdir}/baz", 'bar')

File.write("#{tmpdir}/.dockerignore", '*')

expect(subject).to eq %w(baz)
end
end

def files_in_tar(tar)
Gem::Package::TarReader.new(tar) { |content| return content.map(&:full_name).sort }
end
Expand Down