Skip to content

Commit

Permalink
Handle exclusions when ignoring files
Browse files Browse the repository at this point in the history
Always exclude Dockerfile and .dockerignore from being ignored.

https://docs.docker.com/engine/reference/builder/#dockerignore-file
> You can even use the .dockerignore file to exclude the Dockerfile and .dockerignore files.
> These files are still sent to the daemon because it needs them to do its job.
> But the ADD and COPY instructions do not copy them to the image.

resolves upserve#484
  • Loading branch information
ghostsquad authored and kiela committed May 28, 2019
1 parent 45235b2 commit 9ed83e2
Show file tree
Hide file tree
Showing 2 changed files with 96 additions and 4 deletions.
20 changes: 16 additions & 4 deletions lib/docker/util.rb
Original file line number Diff line number Diff line change
Expand Up @@ -260,7 +260,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 @@ -269,11 +269,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

0 comments on commit 9ed83e2

Please sign in to comment.