oak 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,5 @@
1
+ lib/**/*.rb
2
+ bin/*
3
+ -
4
+ features/**/*.feature
5
+ LICENSE.txt
data/Gemfile ADDED
@@ -0,0 +1,17 @@
1
+ source "http://rubygems.org"
2
+ # Add dependencies required to use your gem here.
3
+ # Example:
4
+ # gem "activesupport", ">= 2.3.5"
5
+
6
+ # Add dependencies to develop your gem here.
7
+ # Include everything needed to run rake, tests, features, etc.
8
+ group :development do
9
+ gem "shoulda", ">= 0"
10
+ gem "bundler", "~> 1.0.0"
11
+ gem "jeweler", "~> 1.6.4"
12
+ gem "rcov", ">= 0"
13
+ gem 'rdoc', "~> 3.11"
14
+ end
15
+
16
+ gem 'thor', "~> 0.14.6"
17
+
@@ -0,0 +1,26 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ git (1.2.5)
5
+ jeweler (1.6.4)
6
+ bundler (~> 1.0)
7
+ git (>= 1.2.5)
8
+ rake
9
+ json (1.6.1)
10
+ rake (0.9.2)
11
+ rcov (0.9.11)
12
+ rdoc (3.11)
13
+ json (~> 1.4)
14
+ shoulda (2.11.3)
15
+ thor (0.14.6)
16
+
17
+ PLATFORMS
18
+ ruby
19
+
20
+ DEPENDENCIES
21
+ bundler (~> 1.0.0)
22
+ jeweler (~> 1.6.4)
23
+ rcov
24
+ rdoc (~> 3.11)
25
+ shoulda
26
+ thor (~> 0.14.6)
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011 Huang Wei
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,34 @@
1
+ ## oak
2
+
3
+ Oak is a very simple tool that assists making rails application Open Source ready.
4
+
5
+ **ONLY WORKS ON MAC OS X AND LINUX/BSD**
6
+
7
+ When pushlishing your rails app to a public repository, it is often neccessary to find a way protecting you secret token and other private information.
8
+
9
+ Oak helps you on these tasks by running
10
+
11
+ oak setup
12
+
13
+ Then your private information will be stored in a file called 'config.yml', and automaticly ignored by git master branch. And on another branch named 'deploy' (which won't be pushed to the public repository) the config.yml file is included.
14
+ So you can modify your apps on master branch as usual, and call
15
+
16
+ git push <production_repo> deploy:master
17
+
18
+ to push your local deploy branch to your production repository's master branch.
19
+
20
+ ## Contributing to oak
21
+
22
+ * Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
23
+ * Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it
24
+ * Fork the project
25
+ * Start a feature/bugfix branch
26
+ * Commit and push until you are happy with your contribution
27
+ * Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
28
+ * Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
29
+
30
+ ## Copyright
31
+
32
+ Copyright (c) 2011 Huang Wei. See LICENSE.txt for
33
+ further details.
34
+
@@ -0,0 +1,53 @@
1
+ # encoding: utf-8
2
+
3
+ require 'rubygems'
4
+ require 'bundler'
5
+ begin
6
+ Bundler.setup(:default, :development)
7
+ rescue Bundler::BundlerError => e
8
+ $stderr.puts e.message
9
+ $stderr.puts "Run `bundle install` to install missing gems"
10
+ exit e.status_code
11
+ end
12
+ require 'rake'
13
+
14
+ require 'jeweler'
15
+ Jeweler::Tasks.new do |gem|
16
+ # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
17
+ gem.name = "oak"
18
+ gem.homepage = "http://github.com/imonyse/oak"
19
+ gem.license = "MIT"
20
+ gem.summary = %Q{Oak is a tool that helps making your newly created rails app open source ready.}
21
+ gem.description = %Q{When pushing your rails app to a public repository, it is often neccessary to find a way protecting you secret token and other private information. Oak helps you on these tasks and assumes you use git as the version control system}
22
+ gem.email = "imonyse@gmail.com"
23
+ gem.authors = ["Huang Wei"]
24
+ # dependencies defined in Gemfile
25
+ end
26
+ Jeweler::RubygemsDotOrgTasks.new
27
+
28
+ require 'rake/testtask'
29
+ Rake::TestTask.new(:test) do |test|
30
+ test.libs << 'lib' << 'test'
31
+ test.pattern = 'test/**/test_*.rb'
32
+ test.verbose = true
33
+ end
34
+
35
+ require 'rcov/rcovtask'
36
+ Rcov::RcovTask.new do |test|
37
+ test.libs << 'test'
38
+ test.pattern = 'test/**/test_*.rb'
39
+ test.verbose = true
40
+ test.rcov_opts << '--exclude "gems/*"'
41
+ end
42
+
43
+ task :default => :test
44
+
45
+ require 'rdoc/task'
46
+ RDoc::Task.new do |rdoc|
47
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
48
+
49
+ rdoc.rdoc_dir = 'rdoc'
50
+ rdoc.title = "oak #{version}"
51
+ rdoc.rdoc_files.include('README*')
52
+ rdoc.rdoc_files.include('lib/**/*.rb')
53
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.0.2
data/bin/oak ADDED
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $LOAD_PATH.unshift File.join(File.dirname(__FILE__), '..', 'lib')
4
+ require 'oak'
5
+
6
+ Oak.start
@@ -0,0 +1,122 @@
1
+ require 'thor'
2
+
3
+ class Oak < Thor
4
+ include Thor::Actions
5
+ attr_reader :secret_token
6
+
7
+ desc "setup oak", "Set current rails app source open ready"
8
+ def setup(working_directory = '.')
9
+ self.destination_root = working_directory
10
+ FileUtils.chdir destination_root do
11
+ check_cfg
12
+ dummy_config
13
+ git_prepare
14
+ create_config_on_deploy
15
+ commit_deploy_branch
16
+ end
17
+ end
18
+
19
+ no_tasks do
20
+
21
+ def check_cfg
22
+ ['config/application.rb', '.gitignore'].each do |f|
23
+ if !File.exists? f
24
+ raise "#{f} not found, are we at the root directory of a rails app?"
25
+ end
26
+ end
27
+
28
+ # make 'config/database.yml' globally ignored
29
+ global_ignore_file = File.expand_path('~/.gitignore')
30
+ if File.exist? global_ignore_file
31
+ ignored = File.binread global_ignore_file
32
+ if !ignored.include?('config/database.yml')
33
+ append_to_file(global_ignore_file, 'config/database.yml')
34
+ end
35
+ else
36
+ File.open(global_ignore_file, 'w') do |f|
37
+ f.write 'config/database.yml'
38
+ end
39
+ end
40
+ `git config --global core.excludesfile ~/.gitignore`
41
+
42
+ # append config/config.yml to .gitignore if not already in
43
+ File.open('.gitignore') do |f|
44
+ f.each_line do |l|
45
+ if l == 'config/config.yml'
46
+ return
47
+ end
48
+ end
49
+ end
50
+
51
+ append_to_file '.gitignore', 'config/config.yml'
52
+
53
+ # protect secret_token
54
+ full_text = File.binread 'config/initializers/secret_token.rb'
55
+ full_text.gsub! /(Application\.config\.secret_token\s=\s)'(.*)'/, '\1APP_CONFIG[\'secret_token\']'
56
+ # save per app secret_token for later use
57
+ @secret_token = "#{$2}"
58
+ File.open('config/initializers/secret_token.rb', 'w') do |f|
59
+ f.write full_text
60
+ end
61
+ end
62
+
63
+ def dummy_config
64
+ File.open('config/config.example.yml', 'w') do |f|
65
+ f.write "secret_token = 'c1cae0f52a3ef8efa369a127c63bd6ede539a4089fd952b33199100a6769c8455ab4969f2eefaf1ebcbe0208bd57531204c77f41f715207f961e7e45f139f4e7'"
66
+ end
67
+ prepend_to_file 'config/application.rb', "require 'yaml'\nAPP_CONFIG = YAML.load(File.read(File.expand_path('../config.yml', __FILE__)))\n"
68
+
69
+ # simply copy database.yml to database.example.yml
70
+ File.open('config/database.example.yml', 'w') do |f|
71
+ File.open('config/database.yml', 'r') do |o|
72
+ f.write o.read
73
+ end
74
+ end
75
+ end
76
+
77
+ def git_prepare
78
+ if File.exists? '.git'
79
+ puts 'It seems a git repository has already created, I\'ll leave it untouched.'
80
+ return
81
+ end
82
+
83
+ `git init && git add . && git commit -m "init"`
84
+ `git checkout -b deploy`
85
+ end
86
+
87
+ def create_config_on_deploy
88
+ File.open('config/config.yml', 'w') do |f|
89
+ f.write 'secret_token = ' + secret_token
90
+ end
91
+
92
+ # remove 'config/config.yml' from .gitignore on deploy branch
93
+ ignored = File.binread('.gitignore')
94
+ ignored.gsub! /config\/config.yml/, ''
95
+ File.open('.gitignore', 'w') do |f|
96
+ f.write ignored
97
+ end
98
+
99
+ # add checkout hook for switching from 'deploy' to 'master'
100
+ File.open('.git/hooks/post-checkout', 'w') do |f|
101
+ f.write <<-EOS
102
+ #!/bin/bash
103
+
104
+ branch_name=$(git symbolic-ref -q HEAD)
105
+ branch_name=${branch_name##refs/heads/}
106
+
107
+ if [ "$branch_name" = master -a -e "config/config.example.yml" ]; then
108
+ cp config/config.example.yml config/config.yml
109
+ echo "cp config/config.example.yml config/config.yml"
110
+ fi
111
+ EOS
112
+ end
113
+ `chmod +x .git/hooks/post-checkout`
114
+ end
115
+
116
+ def commit_deploy_branch
117
+ # commit deploy branch
118
+ `git add . && git commit -m "deploy setup"`
119
+ `git checkout master`
120
+ end
121
+ end
122
+ end
@@ -0,0 +1,71 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{oak}
8
+ s.version = "0.0.2"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = [%q{Huang Wei}]
12
+ s.date = %q{2011-10-24}
13
+ s.description = %q{When pushing your rails app to a public repository, it is often neccessary to find a way protecting you secret token and other private information. Oak helps you on these tasks and assumes you use git as the version control system}
14
+ s.email = %q{imonyse@gmail.com}
15
+ s.executables = [%q{oak}]
16
+ s.extra_rdoc_files = [
17
+ "LICENSE.txt",
18
+ "README.md"
19
+ ]
20
+ s.files = [
21
+ ".document",
22
+ "Gemfile",
23
+ "Gemfile.lock",
24
+ "LICENSE.txt",
25
+ "README.md",
26
+ "Rakefile",
27
+ "VERSION",
28
+ "bin/oak",
29
+ "lib/oak.rb",
30
+ "oak.gemspec",
31
+ "test/files/config/application.rb",
32
+ "test/files/config/database.yml",
33
+ "test/files/config/initializers/secret_token.rb",
34
+ "test/files/dot_gitignore",
35
+ "test/helper.rb",
36
+ "test/test_oak.rb"
37
+ ]
38
+ s.homepage = %q{http://github.com/imonyse/oak}
39
+ s.licenses = [%q{MIT}]
40
+ s.require_paths = [%q{lib}]
41
+ s.rubygems_version = %q{1.8.6}
42
+ s.summary = %q{Oak is a tool that helps making your newly created rails app open source ready.}
43
+
44
+ if s.respond_to? :specification_version then
45
+ s.specification_version = 3
46
+
47
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
48
+ s.add_runtime_dependency(%q<thor>, ["~> 0.14.6"])
49
+ s.add_development_dependency(%q<shoulda>, [">= 0"])
50
+ s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
51
+ s.add_development_dependency(%q<jeweler>, ["~> 1.6.4"])
52
+ s.add_development_dependency(%q<rcov>, [">= 0"])
53
+ s.add_development_dependency(%q<rdoc>, ["~> 3.11"])
54
+ else
55
+ s.add_dependency(%q<thor>, ["~> 0.14.6"])
56
+ s.add_dependency(%q<shoulda>, [">= 0"])
57
+ s.add_dependency(%q<bundler>, ["~> 1.0.0"])
58
+ s.add_dependency(%q<jeweler>, ["~> 1.6.4"])
59
+ s.add_dependency(%q<rcov>, [">= 0"])
60
+ s.add_dependency(%q<rdoc>, ["~> 3.11"])
61
+ end
62
+ else
63
+ s.add_dependency(%q<thor>, ["~> 0.14.6"])
64
+ s.add_dependency(%q<shoulda>, [">= 0"])
65
+ s.add_dependency(%q<bundler>, ["~> 1.0.0"])
66
+ s.add_dependency(%q<jeweler>, ["~> 1.6.4"])
67
+ s.add_dependency(%q<rcov>, [">= 0"])
68
+ s.add_dependency(%q<rdoc>, ["~> 3.11"])
69
+ end
70
+ end
71
+
@@ -0,0 +1,3 @@
1
+ require File.expand_path('../boot', __FILE__)
2
+
3
+ require 'rails/all'
@@ -0,0 +1,25 @@
1
+ # SQLite version 3.x
2
+ # gem install sqlite3
3
+ #
4
+ # Ensure the SQLite 3 gem is defined in your Gemfile
5
+ # gem 'sqlite3'
6
+ development:
7
+ adapter: sqlite3
8
+ database: db/development.sqlite3
9
+ pool: 5
10
+ timeout: 5000
11
+
12
+ # Warning: The database defined as "test" will be erased and
13
+ # re-generated from your development database when you run "rake".
14
+ # Do not set this db to the same as development or production.
15
+ test:
16
+ adapter: sqlite3
17
+ database: db/test.sqlite3
18
+ pool: 5
19
+ timeout: 5000
20
+
21
+ production:
22
+ adapter: sqlite3
23
+ database: db/production.sqlite3
24
+ pool: 5
25
+ timeout: 5000
@@ -0,0 +1,7 @@
1
+ # Be sure to restart your server when you modify this file.
2
+
3
+ # Your secret key for verifying the integrity of signed cookies.
4
+ # If you change this key, all old signed cookies will become invalid!
5
+ # Make sure the secret is at least 30 characters and all random,
6
+ # no regular words or you'll be exposed to dictionary attacks.
7
+ Oak::Application.config.secret_token = 'c1cae0f52a3ef8efa369a127c63bd6ede539a4089fd952b33199100a6769c8455ab4969f2eefaf1ebcbe0208bd57531204c77f41f715207f961e7e45f139f4e7'
File without changes
@@ -0,0 +1,29 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+
4
+ begin
5
+ Bundler.setup(:default, :development)
6
+ rescue Bundler::BundlerError => e
7
+ $stderr.puts e.message
8
+ $stderr.puts "Run `bundle install` to install missing gems"
9
+ exit e.status_code
10
+ end
11
+
12
+ require 'test/unit'
13
+ require 'shoulda'
14
+
15
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
16
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
17
+ require 'oak'
18
+
19
+ class Test::Unit::TestCase
20
+ def create_temp_file(oak_ref)
21
+ oak_ref.destination_root = 'test_tmp'
22
+ FileUtils.cp_r 'test/files', 'test_tmp'
23
+ FileUtils.mv 'test_tmp/dot_gitignore', 'test_tmp/.gitignore'
24
+ end
25
+
26
+ def clear_temp_file(oak_ref)
27
+ FileUtils.rm_rf oak_ref.destination_root
28
+ end
29
+ end
@@ -0,0 +1,44 @@
1
+ require 'helper'
2
+
3
+ class TestOak < Test::Unit::TestCase
4
+ def setup
5
+ @oak = Oak.new
6
+ create_temp_file @oak
7
+ end
8
+
9
+ def teardown
10
+ clear_temp_file @oak
11
+ end
12
+
13
+ def test_check_cfg
14
+ FileUtils.cd @oak.destination_root do
15
+ @oak.check_cfg
16
+ assert_equal('config/config.yml', File.binread('.gitignore'))
17
+ assert_equal('c1cae0f52a3ef8efa369a127c63bd6ede539a4089fd952b33199100a6769c8455ab4969f2eefaf1ebcbe0208bd57531204c77f41f715207f961e7e45f139f4e7', @oak.secret_token)
18
+ ignored = File.binread(File.expand_path('~/.gitignore'))
19
+ assert(ignored.include?('config/database.yml'))
20
+ end
21
+ end
22
+
23
+ def test_create_config_on_deploy
24
+ FileUtils.cd @oak.destination_root do
25
+ @oak.check_cfg
26
+ @oak.git_prepare
27
+ @oak.create_config_on_deploy
28
+ assert_equal('secret_token = ' + @oak.secret_token, File.binread('config/config.yml'))
29
+ end
30
+ end
31
+
32
+ def test_setup
33
+ @oak.setup @oak.destination_root
34
+ FileUtils.chdir @oak.destination_root do
35
+ File.open('.gitignore') do |f|
36
+ lines = f.readlines
37
+ assert_equal('config/config.yml', lines[0].chomp)
38
+ end
39
+
40
+ branch = `git symbolic-ref -q HEAD`.chomp
41
+ assert_equal('refs/heads/master', branch)
42
+ end
43
+ end
44
+ end
metadata ADDED
@@ -0,0 +1,136 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: oak
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Huang Wei
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2011-10-24 00:00:00.000000000Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: thor
16
+ requirement: &2153111440 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: 0.14.6
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: *2153111440
25
+ - !ruby/object:Gem::Dependency
26
+ name: shoulda
27
+ requirement: &2153110120 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ type: :development
34
+ prerelease: false
35
+ version_requirements: *2153110120
36
+ - !ruby/object:Gem::Dependency
37
+ name: bundler
38
+ requirement: &2153109360 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ~>
42
+ - !ruby/object:Gem::Version
43
+ version: 1.0.0
44
+ type: :development
45
+ prerelease: false
46
+ version_requirements: *2153109360
47
+ - !ruby/object:Gem::Dependency
48
+ name: jeweler
49
+ requirement: &2153108380 !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: 1.6.4
55
+ type: :development
56
+ prerelease: false
57
+ version_requirements: *2153108380
58
+ - !ruby/object:Gem::Dependency
59
+ name: rcov
60
+ requirement: &2153107460 !ruby/object:Gem::Requirement
61
+ none: false
62
+ requirements:
63
+ - - ! '>='
64
+ - !ruby/object:Gem::Version
65
+ version: '0'
66
+ type: :development
67
+ prerelease: false
68
+ version_requirements: *2153107460
69
+ - !ruby/object:Gem::Dependency
70
+ name: rdoc
71
+ requirement: &2153106420 !ruby/object:Gem::Requirement
72
+ none: false
73
+ requirements:
74
+ - - ~>
75
+ - !ruby/object:Gem::Version
76
+ version: '3.11'
77
+ type: :development
78
+ prerelease: false
79
+ version_requirements: *2153106420
80
+ description: When pushing your rails app to a public repository, it is often neccessary
81
+ to find a way protecting you secret token and other private information. Oak helps
82
+ you on these tasks and assumes you use git as the version control system
83
+ email: imonyse@gmail.com
84
+ executables:
85
+ - oak
86
+ extensions: []
87
+ extra_rdoc_files:
88
+ - LICENSE.txt
89
+ - README.md
90
+ files:
91
+ - .document
92
+ - Gemfile
93
+ - Gemfile.lock
94
+ - LICENSE.txt
95
+ - README.md
96
+ - Rakefile
97
+ - VERSION
98
+ - bin/oak
99
+ - lib/oak.rb
100
+ - oak.gemspec
101
+ - test/files/config/application.rb
102
+ - test/files/config/database.yml
103
+ - test/files/config/initializers/secret_token.rb
104
+ - test/files/dot_gitignore
105
+ - test/helper.rb
106
+ - test/test_oak.rb
107
+ homepage: http://github.com/imonyse/oak
108
+ licenses:
109
+ - MIT
110
+ post_install_message:
111
+ rdoc_options: []
112
+ require_paths:
113
+ - lib
114
+ required_ruby_version: !ruby/object:Gem::Requirement
115
+ none: false
116
+ requirements:
117
+ - - ! '>='
118
+ - !ruby/object:Gem::Version
119
+ version: '0'
120
+ segments:
121
+ - 0
122
+ hash: 2735190199071783322
123
+ required_rubygems_version: !ruby/object:Gem::Requirement
124
+ none: false
125
+ requirements:
126
+ - - ! '>='
127
+ - !ruby/object:Gem::Version
128
+ version: '0'
129
+ requirements: []
130
+ rubyforge_project:
131
+ rubygems_version: 1.8.6
132
+ signing_key:
133
+ specification_version: 3
134
+ summary: Oak is a tool that helps making your newly created rails app open source
135
+ ready.
136
+ test_files: []