ki-repo 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|