ki-repo 0.1.0 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +26 -12
- data/VERSION +1 -1
- data/bin/ki +21 -0
- data/docs/backlog.md +35 -0
- data/docs/development.md +45 -0
- data/docs/development_setup.md +49 -0
- data/{lib/ki-repo.rb → docs/images/for_git.txt} +0 -0
- data/docs/ki_commands.md +202 -0
- data/docs/repository_basics.md +171 -0
- data/docs/writing_extensions.md +50 -0
- data/lib/cmd/cmd.rb +224 -0
- data/lib/cmd/user_pref_cmd.rb +122 -0
- data/lib/cmd/version_cmd.rb +483 -0
- data/lib/data_access/repository_finder.rb +200 -0
- data/lib/data_access/repository_info.rb +153 -0
- data/lib/data_access/version_helpers.rb +242 -0
- data/lib/data_access/version_iterators.rb +145 -0
- data/lib/data_access/version_operations.rb +80 -0
- data/lib/data_storage/dir_base.rb +106 -0
- data/lib/data_storage/ki_home.rb +44 -0
- data/lib/data_storage/ki_json.rb +153 -0
- data/lib/data_storage/repository.rb +91 -0
- data/lib/data_storage/version_metadata.rb +141 -0
- data/lib/ki_repo_all.rb +42 -0
- data/lib/util/attr_chain.rb +258 -0
- data/lib/util/exception_catcher.rb +118 -0
- data/lib/util/hash.rb +46 -0
- data/lib/util/hash_cache.rb +31 -0
- data/lib/util/ruby_extensions.rb +137 -0
- data/lib/util/service_registry.rb +88 -0
- data/lib/util/simple_optparse.rb +103 -0
- data/lib/util/test.rb +323 -0
- metadata +69 -13
- data/.document +0 -5
- data/.rspec +0 -1
- data/Gemfile +0 -14
- data/Gemfile.lock +0 -38
- data/Rakefile +0 -42
- data/spec/ki-repo_spec.rb +0 -6
- data/spec/spec_helper.rb +0 -12
@@ -0,0 +1,153 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
# Copyright 2012 Mikko Apo
|
4
|
+
#
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
# you may not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
# See the License for the specific language governing permissions and
|
15
|
+
# limitations under the License.
|
16
|
+
|
17
|
+
module Ki
|
18
|
+
# Combines version's information from all different repositories
|
19
|
+
# @see Component
|
20
|
+
# @see Repository::Version
|
21
|
+
# @see Repository::Component
|
22
|
+
# @see VersionIterator
|
23
|
+
# @see RepositoryFinder
|
24
|
+
# @see FileFinder
|
25
|
+
# @see VersionMetadataFile
|
26
|
+
# @see VersionStatusFile
|
27
|
+
class Version
|
28
|
+
attr_chain :component, :require
|
29
|
+
attr_chain :name, :require
|
30
|
+
attr_chain :version_id, :require
|
31
|
+
attr_chain :metadata, -> { find_metadata }
|
32
|
+
attr_chain :binaries, -> { find_binaries }
|
33
|
+
attr_chain :finder, -> { component.finder }
|
34
|
+
attr_chain :versions, :require
|
35
|
+
attr_chain :statuses, -> { collect_statuses }
|
36
|
+
|
37
|
+
# finds first Repository::Version directory for this version that contains binaries
|
38
|
+
def find_binaries
|
39
|
+
finder.all_repositories.each do |package_root|
|
40
|
+
binary_dir = package_root.go(version_id)
|
41
|
+
if binary_dir.exists?
|
42
|
+
return binary_dir
|
43
|
+
end
|
44
|
+
end
|
45
|
+
nil
|
46
|
+
end
|
47
|
+
|
48
|
+
# finds first Repository::Version directory that contains metadata
|
49
|
+
def find_metadata
|
50
|
+
versions.each do |v|
|
51
|
+
m = v.metadata
|
52
|
+
if m.exists?
|
53
|
+
return m
|
54
|
+
end
|
55
|
+
end
|
56
|
+
nil
|
57
|
+
end
|
58
|
+
|
59
|
+
# collects all statuses related to this version
|
60
|
+
def collect_statuses
|
61
|
+
ret = []
|
62
|
+
versions.each do |v|
|
63
|
+
s = v.statuses
|
64
|
+
if s.exists?
|
65
|
+
v.statuses.each do |status|
|
66
|
+
ret << [status["key"], status["value"]]
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
ret
|
71
|
+
end
|
72
|
+
|
73
|
+
# finds all versions referenced by this version
|
74
|
+
def version_iterator
|
75
|
+
VersionIterator.new.version(self)
|
76
|
+
end
|
77
|
+
|
78
|
+
# finds files from this version (recursive)
|
79
|
+
def find_files(*file_patterns)
|
80
|
+
FileFinder.new.version(self).files(file_patterns)
|
81
|
+
end
|
82
|
+
|
83
|
+
def exists?
|
84
|
+
metadata || binaries
|
85
|
+
end
|
86
|
+
|
87
|
+
# Initializes a Version and Repository::Version for files non-imported files
|
88
|
+
# * works for testing and showing
|
89
|
+
def self.create_version(file, binary_directory=nil)
|
90
|
+
dir = File.dirname(file)
|
91
|
+
if dir == "."
|
92
|
+
dir = Dir.pwd
|
93
|
+
end
|
94
|
+
version = Version.new
|
95
|
+
repo_ver = Repository::Version.new(dir)
|
96
|
+
repo_ver.metadata = VersionMetadataFile.new(File.basename(file)).parent(repo_ver)
|
97
|
+
version.versions=[repo_ver]
|
98
|
+
if binary_directory
|
99
|
+
version.binaries = DirectoryBase.new(binary_directory)
|
100
|
+
end
|
101
|
+
version
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
# Combine's component's information from all different repositories
|
106
|
+
# @see Repository::Component
|
107
|
+
# @see RepositoryFinder
|
108
|
+
class Component
|
109
|
+
attr_chain :component_id, :require
|
110
|
+
# Package collector contains
|
111
|
+
attr_chain :finder, :require
|
112
|
+
attr_chain :versions, -> { find_versions }
|
113
|
+
attr_chain :status_info, -> { find_status_info }
|
114
|
+
attr_chain :components, :require
|
115
|
+
|
116
|
+
# Returns version list from first component which has a version list
|
117
|
+
def find_versions
|
118
|
+
components.each do |c|
|
119
|
+
version_list_file = c.versions
|
120
|
+
if version_list_file.exists?
|
121
|
+
return version_list_file
|
122
|
+
end
|
123
|
+
end
|
124
|
+
nil
|
125
|
+
end
|
126
|
+
|
127
|
+
# Returns Version which references all existing version directories
|
128
|
+
# @see Version
|
129
|
+
def version_by_id(version_str)
|
130
|
+
version_id = File.join(component_id, version_str)
|
131
|
+
finder.versions.cache(version_id) do
|
132
|
+
info_versions = components.map do |c|
|
133
|
+
Repository::Version.new(version_str).version_id(version_id).parent(c)
|
134
|
+
end
|
135
|
+
existing_versions = info_versions.select do |v|
|
136
|
+
v.exists?
|
137
|
+
end
|
138
|
+
Version.new.component(self).version_id(version_id).name(version_str).versions(existing_versions)
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
def find_status_info
|
143
|
+
ret = {}
|
144
|
+
components.each do |c|
|
145
|
+
si = c.status_info
|
146
|
+
if si.exists?
|
147
|
+
ret.merge!(si.cached_data)
|
148
|
+
end
|
149
|
+
end
|
150
|
+
ret
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
@@ -0,0 +1,242 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
# Copyright 2012 Mikko Apo
|
4
|
+
#
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
# you may not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
# See the License for the specific language governing permissions and
|
15
|
+
# limitations under the License.
|
16
|
+
|
17
|
+
module Ki
|
18
|
+
# Tests that a version is intact. Version can be in repository or as file.
|
19
|
+
# Checks that all files have correct hashes. If recursive is set to true, goes through all dependencies
|
20
|
+
# @see test_version
|
21
|
+
class VersionTester
|
22
|
+
attr_chain :ki_home, :require
|
23
|
+
attr_chain :finder, -> { ki_home.finder }
|
24
|
+
attr_chain :recursive, -> { true }
|
25
|
+
attr_chain :print, -> { false }
|
26
|
+
attr_chain :results, -> { Hash.new }
|
27
|
+
|
28
|
+
# Tests that a version is intact
|
29
|
+
# * test_version(version) expects a Version parameter
|
30
|
+
# @see VersionIterator
|
31
|
+
# @see RepositoryFinder
|
32
|
+
# @return [bool] returns true if there weren't any problems with the version
|
33
|
+
def test_version(root_version, &block)
|
34
|
+
all_ok = true
|
35
|
+
possible_hashes = KiCommand::KiExtensions.find!("/hashing")
|
36
|
+
# iterates through all versions
|
37
|
+
root_version.version_iterator.iterate_versions do |v|
|
38
|
+
binaries = v.binaries
|
39
|
+
metadata = v.metadata
|
40
|
+
metadata.cached_data
|
41
|
+
metadata.files.each do |file_hash|
|
42
|
+
file_path = file_hash["path"]
|
43
|
+
full_path = binaries.path(file_path)
|
44
|
+
issue = nil
|
45
|
+
if !File.exists?(full_path)
|
46
|
+
issue="missing"
|
47
|
+
elsif File.size(full_path) != file_hash["size"]
|
48
|
+
issue="wrong size"
|
49
|
+
elsif !verify_hash(file_hash, full_path, possible_hashes)
|
50
|
+
issue="wrong hash"
|
51
|
+
end
|
52
|
+
if issue
|
53
|
+
all_ok = false
|
54
|
+
(results[issue]||=[]) << [v, file_path]
|
55
|
+
if block
|
56
|
+
block.call(issue, v, file_path)
|
57
|
+
end
|
58
|
+
if print
|
59
|
+
puts "#{v.metadata.path}: '#{file_path}' #{issue} '#{v.binaries.path(file_path)}'"
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
if !recursive
|
64
|
+
break
|
65
|
+
end
|
66
|
+
end
|
67
|
+
all_ok
|
68
|
+
end
|
69
|
+
|
70
|
+
def verify_hash(file_hash, full_path, possible_hashes)
|
71
|
+
file_hashes = possible_hashes.service_names.select { |name| file_hash.include?(name) }
|
72
|
+
checked_hashes = VersionMetadataFile.calculate_hashes(full_path, file_hashes)
|
73
|
+
checked_hashes.each_pair do |id, result|
|
74
|
+
if file_hash[id] != result
|
75
|
+
return false
|
76
|
+
end
|
77
|
+
end
|
78
|
+
true
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
# Imports a version to KiHome
|
83
|
+
class VersionImporter
|
84
|
+
attr_chain :ki_home, :require
|
85
|
+
attr_chain :finder, -> { ki_home.finder}
|
86
|
+
attr_chain :tester, -> { VersionTester.new.recursive(false).print(true) }
|
87
|
+
attr_chain :move_files
|
88
|
+
attr_chain :create_new_version
|
89
|
+
attr_chain :specific_version_id
|
90
|
+
|
91
|
+
# Imports a version to KiHome
|
92
|
+
# * import(file, binary_directory) expects two String parameters defining version file location and directory base for binaries
|
93
|
+
def import(*args)
|
94
|
+
if args.size == 2
|
95
|
+
file, input = args
|
96
|
+
source = DirectoryBase.new(input)
|
97
|
+
metadata = VersionMetadataFile.new(file)
|
98
|
+
else
|
99
|
+
raise "Not supported: '#{args.inspect}'"
|
100
|
+
end
|
101
|
+
test_version(file, input)
|
102
|
+
|
103
|
+
import_from_metadata(metadata, source)
|
104
|
+
end
|
105
|
+
|
106
|
+
def import_from_metadata(metadata, source=nil)
|
107
|
+
if defined?(@specific_version_id) && defined?(@create_new_version)
|
108
|
+
raise "Can't define both specific_version_id '#{specific_version_id}' and create_new_version '#{create_new_version}'!"
|
109
|
+
end
|
110
|
+
|
111
|
+
if defined?(@specific_version_id)
|
112
|
+
version_id = @specific_version_id
|
113
|
+
elsif defined? @create_new_version
|
114
|
+
component_id = @create_new_version
|
115
|
+
version = finder.version(component_id)
|
116
|
+
if version
|
117
|
+
id = version.version_id.split("/").last
|
118
|
+
version_number = (Integer(id) + 1).to_s
|
119
|
+
else
|
120
|
+
version_number = "1"
|
121
|
+
end
|
122
|
+
version_id = File.join(component_id, version_number)
|
123
|
+
else
|
124
|
+
version_id = metadata.version_id
|
125
|
+
end
|
126
|
+
|
127
|
+
version_arr = version_id.split("/")
|
128
|
+
version_number = version_arr.delete_at(-1)
|
129
|
+
component_id = version_arr.join("/")
|
130
|
+
|
131
|
+
version = finder.version(version_id)
|
132
|
+
if version && version.exists?
|
133
|
+
raise "'#{version_id}' exists in repository already!"
|
134
|
+
end
|
135
|
+
|
136
|
+
# creates directories
|
137
|
+
components_dir = ki_home.repositories.add_item("local").mkdir.components
|
138
|
+
binary_dest = metadata_dir = components_dir.add_item(component_id).mkdir.versions.add_version(version_number).mkdir
|
139
|
+
|
140
|
+
metadata_dir.metadata.cached_data = metadata.cached_data
|
141
|
+
metadata_dir.metadata.version_id = version_id
|
142
|
+
metadata_dir.metadata.save
|
143
|
+
if defined? @move_files
|
144
|
+
FileUtils.rm(metadata.path)
|
145
|
+
end
|
146
|
+
source_dirs = []
|
147
|
+
metadata_dir.metadata.files.each do |file_info|
|
148
|
+
file_path = file_info["path"]
|
149
|
+
dir = File.dirname(file_path)
|
150
|
+
if dir != "."
|
151
|
+
source_dirs << dir
|
152
|
+
binary_dest.mkdir(dir)
|
153
|
+
end
|
154
|
+
to_repo(source.path(file_path), binary_dest.path(file_path))
|
155
|
+
end
|
156
|
+
delete_empty_source_dirs(source, source_dirs)
|
157
|
+
end
|
158
|
+
|
159
|
+
|
160
|
+
def delete_empty_source_dirs(source, source_dirs)
|
161
|
+
if defined? @move_files
|
162
|
+
expanded_source_dirs = {}
|
163
|
+
source_dirs.each do |d|
|
164
|
+
dir_entries(d).each do |expanded|
|
165
|
+
expanded_source_dirs[expanded] = true
|
166
|
+
end
|
167
|
+
end
|
168
|
+
expanded_source_dirs.keys.each do |dir|
|
169
|
+
checked_dir = source.path(dir)
|
170
|
+
if Dir.entries(checked_dir) == [".", ".."]
|
171
|
+
FileUtils.rmdir(checked_dir)
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
# splits dir path in to all components: foo/bar/baz, foo/bar, foo
|
178
|
+
def dir_entries(str)
|
179
|
+
arr = str.split("/")
|
180
|
+
ret = []
|
181
|
+
c = arr.size
|
182
|
+
while (c > 0)
|
183
|
+
ret << File.join(arr[0..c])
|
184
|
+
c-=1
|
185
|
+
end
|
186
|
+
ret
|
187
|
+
end
|
188
|
+
|
189
|
+
def to_repo(src, dest)
|
190
|
+
if defined? @move_files
|
191
|
+
FileUtils.mv(src, dest)
|
192
|
+
else
|
193
|
+
FileUtils.cp(src, dest)
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
def test_version(file, input)
|
198
|
+
all_ok = tester.ki_home(ki_home).test_version(Version.create_version(file, input))
|
199
|
+
if !all_ok
|
200
|
+
raise "Files are not ok!"
|
201
|
+
end
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
# Exports a version to directory
|
206
|
+
# * if test_dependencies set to true, tests the version before exporting
|
207
|
+
class VersionExporter
|
208
|
+
attr_chain :ki_home, :require
|
209
|
+
attr_chain :finder, -> { ki_home.finder }
|
210
|
+
attr_chain :test_dependencies
|
211
|
+
attr_chain :find_files, -> { FileFinder.new }
|
212
|
+
attr_chain :copy
|
213
|
+
|
214
|
+
# Exports a version to directory
|
215
|
+
def export(version, out)
|
216
|
+
ver = finder.version(version)
|
217
|
+
if test_dependencies
|
218
|
+
test_version(ver)
|
219
|
+
end
|
220
|
+
files = find_files.version(ver).file_map.sort
|
221
|
+
files.each do |file_path, full_path|
|
222
|
+
dir = File.dirname(file_path)
|
223
|
+
if dir != "."
|
224
|
+
FileUtils.mkdir_p File.join(out, dir)
|
225
|
+
end
|
226
|
+
if defined? @copy
|
227
|
+
FileUtils.cp(full_path, File.join(out, file_path))
|
228
|
+
else
|
229
|
+
FileUtils.ln_sf(full_path, File.join(out, file_path))
|
230
|
+
end
|
231
|
+
end
|
232
|
+
end
|
233
|
+
|
234
|
+
def test_version(version)
|
235
|
+
tester = VersionTester.new.ki_home(ki_home).finder(finder).recursive(true).print(true)
|
236
|
+
all_ok = tester.test_version(version)
|
237
|
+
if !all_ok
|
238
|
+
raise "Files are not ok!"
|
239
|
+
end
|
240
|
+
end
|
241
|
+
end
|
242
|
+
end
|
@@ -0,0 +1,145 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
# Copyright 2012 Mikko Apo
|
4
|
+
#
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
# you may not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
# See the License for the specific language governing permissions and
|
15
|
+
# limitations under the License.
|
16
|
+
|
17
|
+
module Ki
|
18
|
+
#
|
19
|
+
#
|
20
|
+
class VersionIterator
|
21
|
+
attr_chain :version, :require
|
22
|
+
attr_chain :dependency
|
23
|
+
attr_chain :package_path
|
24
|
+
attr_chain :dependency_path
|
25
|
+
attr_chain :finder, -> { version.component.finder }
|
26
|
+
attr_chain :block
|
27
|
+
attr_chain :internals
|
28
|
+
attr_chain :exclude_dependencies, -> { [] }, :convert => lambda { |list| Array.wrap(list).map { |s| /#{s}/ } }
|
29
|
+
|
30
|
+
def iterate_versions(&block)
|
31
|
+
start_iteration do |version_iterator|
|
32
|
+
block.call(version_iterator.version)
|
33
|
+
version_iterator.iterate_dependencies
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def start_iteration(&block)
|
38
|
+
@block = block
|
39
|
+
@internals = true
|
40
|
+
block.call(self)
|
41
|
+
end
|
42
|
+
|
43
|
+
def iterate_dependencies
|
44
|
+
version.metadata.dependencies.map do |dep|
|
45
|
+
if internals || !dep["internal"]
|
46
|
+
dep_v = VersionIterator.new
|
47
|
+
dep_v.version = finder.version(dep["version_id"])
|
48
|
+
dep_v.dependency = dep
|
49
|
+
dep_v.exclude_dependencies.concat(exclude_dependencies).concat(select_dep_rm(dep))
|
50
|
+
dep_v.block = block
|
51
|
+
if dep["path"] || package_path
|
52
|
+
dep_v.package_path = File.join([package_path, dep["path"]].compact)
|
53
|
+
end
|
54
|
+
if dependency_path || dep["name"]
|
55
|
+
dep_v.dependency_path = File.join([dependency_path, dep["name"]].compact)
|
56
|
+
end
|
57
|
+
if ok_to_iterate_dependency(dep_v)
|
58
|
+
[dep, dep_v.version, block.call(dep_v)]
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end.compact
|
62
|
+
end
|
63
|
+
|
64
|
+
def select_dep_rm(dep_v)
|
65
|
+
ops = dep_v["operations"]
|
66
|
+
if ops
|
67
|
+
ops.map do |op|
|
68
|
+
if op.first == "dep-rm"
|
69
|
+
op[1..-1]
|
70
|
+
end
|
71
|
+
end.compact.flatten
|
72
|
+
else
|
73
|
+
[]
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def ok_to_iterate_dependency(dep_v)
|
78
|
+
!(exclude_dependencies.size > 0 && (exclude_dependencies.any_matches?(dep_v.version.version_id) || dep_v.dependency_path && exclude_dependencies.any_matches?(dep_v.dependency_path)))
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
class FileFinder < VersionIterator
|
83
|
+
attr_chain :files, -> { [] }, :convert => lambda { |list| Array.wrap(list).map { |s| FileRegexp.matcher(s) } }
|
84
|
+
attr_chain :exclude_files, -> { [] }, :convert => lambda { |list| Array.wrap(list).map { |s| FileRegexp.matcher(s) } }
|
85
|
+
attr_chain :tags, -> { [] }, :convert => lambda { |list| Array.wrap(list)}
|
86
|
+
attr_chain :exclude_tags, -> { [] }, :convert => lambda { |list| Array.wrap(list)}
|
87
|
+
|
88
|
+
def file_map
|
89
|
+
start_iteration do |ver_iterator|
|
90
|
+
ret = {}
|
91
|
+
ver_iterator.iterate_dependencies.each do |dependency, version, file_map|
|
92
|
+
file_operations(file_map, dependency)
|
93
|
+
ret.merge!(file_map)
|
94
|
+
end
|
95
|
+
ver = ver_iterator.version
|
96
|
+
binaries = ver.binaries
|
97
|
+
metadata = ver.metadata
|
98
|
+
# TODO: file operations should be applied to the files before the files are filtered
|
99
|
+
metadata.files.each do |file|
|
100
|
+
path = file["path"]
|
101
|
+
file_path = File.join([ver_iterator.package_path, path].compact)
|
102
|
+
if ok_to_add_file(file, file_path)
|
103
|
+
ret[file_path]=binaries.path(path)
|
104
|
+
end
|
105
|
+
end
|
106
|
+
file_operations(ret, metadata.cached_data)
|
107
|
+
ret
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
def file_list
|
112
|
+
file_map.values
|
113
|
+
end
|
114
|
+
|
115
|
+
# Modifies
|
116
|
+
def file_operations(file_map, dependency)
|
117
|
+
operations = dependency["operations"]
|
118
|
+
if operations
|
119
|
+
VersionFileOperations.new.edit_file_map(file_map, operations)
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
# File is added to the list if
|
124
|
+
# - files pattern list is empty (select all files) or file path matches any files pattern
|
125
|
+
# - it does not match any file exclude patterns
|
126
|
+
# - tags selection list is empty or file has any tags from tags selection list
|
127
|
+
# - no tags match tags from tags exclusion list
|
128
|
+
def ok_to_add_file(file, file_path)
|
129
|
+
file_tags = file["tags"] || []
|
130
|
+
(files.size == 0 || files.any_matches?(file_path)) &&
|
131
|
+
!exclude_files.any_matches?(file_path) &&
|
132
|
+
(tags.size == 0 || (cross_any_matches?(file_tags, tags)) &&
|
133
|
+
!cross_any_matches?(file_tags, exclude_tags))
|
134
|
+
end
|
135
|
+
|
136
|
+
def cross_any_matches?(arr, dest_arr)
|
137
|
+
arr.each do |i|
|
138
|
+
if dest_arr.any_matches?(i)
|
139
|
+
return true
|
140
|
+
end
|
141
|
+
end
|
142
|
+
false
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
# Copyright 2012 Mikko Apo
|
4
|
+
#
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
# you may not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
# See the License for the specific language governing permissions and
|
15
|
+
# limitations under the License.
|
16
|
+
|
17
|
+
module Ki
|
18
|
+
class VersionFileOperations
|
19
|
+
def resolve_dest_file(file, dest, matching_pattern)
|
20
|
+
matcher = matching_pattern.match(file)
|
21
|
+
dest = dest.gsub(/\$\d/) do |str|
|
22
|
+
matcher[Integer(str[1..-1])]
|
23
|
+
end
|
24
|
+
if dest.end_with?("/")
|
25
|
+
dest = File.join(dest, File.basename(file))
|
26
|
+
end
|
27
|
+
if dest.start_with?("/")
|
28
|
+
dest = dest[1..-1]
|
29
|
+
end
|
30
|
+
dest
|
31
|
+
end
|
32
|
+
|
33
|
+
def copy_or_move(file_map, args, op)
|
34
|
+
delete = op == "mv"
|
35
|
+
dest = args.delete_at(-1)
|
36
|
+
patterns = args.map { |pattern| FileRegexp.matcher(pattern) }
|
37
|
+
matching_files = []
|
38
|
+
file_map.keys.each do |file|
|
39
|
+
matching_pattern = patterns.any_matches?(file)
|
40
|
+
if matching_pattern
|
41
|
+
matching_files << file
|
42
|
+
dest_file = resolve_dest_file(file, dest, matching_pattern)
|
43
|
+
file_map[dest_file]=file_map[file]
|
44
|
+
if delete
|
45
|
+
file_map.delete(file)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def delete(file_map, args, op)
|
52
|
+
patterns = args.map { |pattern| FileRegexp.matcher(pattern) }
|
53
|
+
file_map.keys.each do |file|
|
54
|
+
if patterns.any_matches?(file)
|
55
|
+
file_map.delete(file)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def edit_file_map(file_map, operations)
|
61
|
+
operations.each do |op, *args|
|
62
|
+
case op
|
63
|
+
when "cp"
|
64
|
+
copy_or_move(file_map, args, op)
|
65
|
+
when "mv"
|
66
|
+
copy_or_move(file_map, args, op)
|
67
|
+
when "rm"
|
68
|
+
delete(file_map, args, op)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
74
|
+
|
75
|
+
class FileRegexp
|
76
|
+
def FileRegexp.matcher(s)
|
77
|
+
/^#{s.gsub(/\./, '\.').gsub('*', ".*")}$/
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|