tetra 0.40.0 → 0.41.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +1 -1
- data/Gemfile +2 -0
- data/Gemfile.lock +48 -0
- data/MOTIVATION.md +9 -3
- data/README.md +5 -5
- data/SPECIAL_CASES.md +1 -3
- data/integration-tests/{commons.sh → build-commons.sh} +26 -6
- data/integration-tests/build-obs.sh +21 -0
- data/lib/template/kit_item.spec +53 -0
- data/lib/template/package.spec +4 -2
- data/lib/tetra.rb +5 -3
- data/lib/tetra/archiver.rb +23 -87
- data/lib/tetra/commands/generate_all.rb +13 -16
- data/lib/tetra/commands/generate_kit_archive.rb +4 -4
- data/lib/tetra/commands/generate_kit_spec.rb +4 -2
- data/lib/tetra/commands/generate_package_archive.rb +1 -1
- data/lib/tetra/commands/generate_package_spec.rb +2 -2
- data/lib/tetra/git.rb +19 -10
- data/lib/tetra/glue_kit_item.rb +42 -0
- data/lib/tetra/jar_kit_item.rb +45 -0
- data/lib/tetra/kit.rb +73 -0
- data/lib/tetra/maven_kit_item.rb +64 -0
- data/lib/tetra/package.rb +82 -0
- data/lib/tetra/project.rb +26 -22
- data/lib/tetra/spec_generator.rb +38 -42
- data/lib/tetra/version.rb +1 -1
- data/spec/lib/archiver_spec.rb +30 -86
- data/spec/lib/git_spec.rb +8 -8
- data/spec/lib/glue_kit_item_spec.rb +31 -0
- data/spec/lib/kit_spec.rb +67 -0
- data/spec/lib/maven_kit_item_spec.rb +74 -0
- data/spec/lib/package_spec.rb +78 -0
- data/spec/lib/project_spec.rb +1 -1
- data/spec/lib/spec_generator_spec.rb +59 -87
- metadata +15 -8
- data/lib/template/kit.spec +0 -64
- data/lib/tetra/kit_spec_adapter.rb +0 -28
- data/lib/tetra/package_spec_adapter.rb +0 -59
- data/lib/tetra/template_manager.rb +0 -33
- data/spec/lib/template_manager_spec.rb +0 -54
@@ -3,14 +3,14 @@
|
|
3
3
|
module Tetra
|
4
4
|
# tetra generate-kit-archive
|
5
5
|
class GenerateKitArchiveCommand < Tetra::BaseCommand
|
6
|
-
option %w(-w --whole), :flag, "recreate the whole archive (not incremental)"
|
7
|
-
|
8
6
|
def execute
|
9
7
|
checking_exceptions do
|
10
8
|
project = Tetra::Project.new(".")
|
11
9
|
ensure_dry_running(false, project) do
|
12
|
-
|
13
|
-
|
10
|
+
Tetra::Kit.new(project).items.each do |item|
|
11
|
+
result_path = item.to_archive
|
12
|
+
print_generation_result(project, result_path)
|
13
|
+
end
|
14
14
|
end
|
15
15
|
end
|
16
16
|
end
|
@@ -7,8 +7,10 @@ module Tetra
|
|
7
7
|
checking_exceptions do
|
8
8
|
project = Tetra::Project.new(".")
|
9
9
|
ensure_dry_running(false, project) do
|
10
|
-
|
11
|
-
|
10
|
+
Tetra::Kit.new(project).items.each do |item|
|
11
|
+
result_path, conflict_count = item.to_spec
|
12
|
+
print_generation_result(project, result_path, conflict_count)
|
13
|
+
end
|
12
14
|
end
|
13
15
|
end
|
14
16
|
end
|
@@ -10,7 +10,7 @@ module Tetra
|
|
10
10
|
project = Tetra::Project.new(".")
|
11
11
|
ensure_dry_running(false, project) do
|
12
12
|
package_name = project.get_package_name(directory)
|
13
|
-
result_path = Tetra::
|
13
|
+
result_path = Tetra::Package.new(project, package_name).to_archive
|
14
14
|
print_generation_result(project, result_path)
|
15
15
|
end
|
16
16
|
end
|
@@ -12,8 +12,8 @@ module Tetra
|
|
12
12
|
project = Tetra::Project.new(".")
|
13
13
|
ensure_dry_running(false, project) do
|
14
14
|
package_name = project.get_package_name(directory)
|
15
|
-
result_path, conflict_count =
|
16
|
-
.
|
15
|
+
result_path, conflict_count =
|
16
|
+
Tetra::Package.new(project, package_name, pom, filter).to_spec
|
17
17
|
print_generation_result(project, result_path, conflict_count)
|
18
18
|
end
|
19
19
|
end
|
data/lib/tetra/git.rb
CHANGED
@@ -46,10 +46,10 @@ module Tetra
|
|
46
46
|
end
|
47
47
|
end
|
48
48
|
|
49
|
-
# adds all files in the current directory
|
50
|
-
# all files not in the current directory
|
51
|
-
#
|
52
|
-
def commit_whole_directory(message, tag
|
49
|
+
# adds all files in the current directory, removes
|
50
|
+
# all files not in the current directory, commits
|
51
|
+
# and tags with prefix
|
52
|
+
def commit_whole_directory(message, tag, tag_message = nil)
|
53
53
|
Dir.chdir(@directory) do
|
54
54
|
log.debug "committing with message: #{message}"
|
55
55
|
|
@@ -65,16 +65,25 @@ module Tetra
|
|
65
65
|
`git add .`
|
66
66
|
`git commit -m "#{message}"`
|
67
67
|
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
`git tag tetra_#{tag}`
|
73
|
-
end
|
68
|
+
if !tag_message.nil?
|
69
|
+
`git tag tetra_#{tag} -m "#{tag_message}"`
|
70
|
+
else
|
71
|
+
`git tag tetra_#{tag}`
|
74
72
|
end
|
75
73
|
end
|
76
74
|
end
|
77
75
|
|
76
|
+
# commits and tags one single file
|
77
|
+
# if tag is given, commit is also tagged
|
78
|
+
def commit_file(path, message, tag)
|
79
|
+
Dir.chdir(@directory) do
|
80
|
+
log.debug "committing path #{path} with message: #{message}"
|
81
|
+
`git add #{path}`
|
82
|
+
`git commit -m "#{message}"`
|
83
|
+
`git tag tetra_#{tag}`
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
78
87
|
# returns the highest suffix found in tags with the given prefix
|
79
88
|
def get_tag_maximum_suffix(prefix)
|
80
89
|
Dir.chdir(@directory) do
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
module Tetra
|
4
|
+
# represents a prebuilt package dependency from a jar file
|
5
|
+
# in a kit
|
6
|
+
class GlueKitItem
|
7
|
+
# implement to_spec
|
8
|
+
include SpecGenerator
|
9
|
+
attr_reader :project
|
10
|
+
attr_reader :package_name
|
11
|
+
attr_reader :spec_dir
|
12
|
+
attr_reader :template_spec_name
|
13
|
+
attr_reader :conflicts
|
14
|
+
|
15
|
+
# implement to_archive
|
16
|
+
include Archiver
|
17
|
+
attr_reader :source_dir
|
18
|
+
attr_reader :source_paths
|
19
|
+
attr_reader :destination_dir
|
20
|
+
|
21
|
+
# template-specific attributes
|
22
|
+
attr_reader :provides_symbol
|
23
|
+
attr_reader :provides_version
|
24
|
+
attr_reader :install_dir
|
25
|
+
|
26
|
+
def initialize(project, source_paths)
|
27
|
+
@project = project
|
28
|
+
@package_name = "kit-item-glue-#{project.name}"
|
29
|
+
@spec_dir = "kit"
|
30
|
+
@template_spec_name = "kit_item.spec"
|
31
|
+
@conflicts = true
|
32
|
+
|
33
|
+
@source_dir = File.join("kit")
|
34
|
+
@source_paths = source_paths
|
35
|
+
@destination_dir = @package_name
|
36
|
+
|
37
|
+
@provides_symbol = "tetra-glue"
|
38
|
+
@provides_version = "#{project.name}-#{project.version}"
|
39
|
+
@install_dir = ""
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
module Tetra
|
4
|
+
# represents a prebuilt package dependency from a jar file
|
5
|
+
# in a kit
|
6
|
+
class JarKitItem
|
7
|
+
# implement to_spec
|
8
|
+
include SpecGenerator
|
9
|
+
attr_reader :project
|
10
|
+
attr_reader :package_name
|
11
|
+
attr_reader :spec_dir
|
12
|
+
attr_reader :template_spec_name
|
13
|
+
attr_reader :conflicts
|
14
|
+
|
15
|
+
# implement to_archive
|
16
|
+
include Archiver
|
17
|
+
attr_reader :source_dir
|
18
|
+
attr_reader :source_paths
|
19
|
+
attr_reader :destination_dir
|
20
|
+
|
21
|
+
# template-specific attributes
|
22
|
+
attr_reader :provides_symbol
|
23
|
+
attr_reader :provides_version
|
24
|
+
attr_reader :install_dir
|
25
|
+
|
26
|
+
def initialize(project, path)
|
27
|
+
_, name = Pathname.new(path).split
|
28
|
+
hash = Digest::SHA1.file(path).hexdigest
|
29
|
+
|
30
|
+
@project = project
|
31
|
+
@package_name = "kit-item-#{name.to_s.gsub(".", "-")}"
|
32
|
+
@spec_dir = "kit"
|
33
|
+
@template_spec_name = "kit_item.spec"
|
34
|
+
@conflicts = false
|
35
|
+
|
36
|
+
@source_dir = File.join("kit", "jars")
|
37
|
+
@source_paths = [path]
|
38
|
+
@destination_dir = @package_name
|
39
|
+
|
40
|
+
@provides_symbol = "tetra-jar(#{name})"
|
41
|
+
@provides_version = hash
|
42
|
+
@install_dir = "jars"
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
data/lib/tetra/kit.rb
ADDED
@@ -0,0 +1,73 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
module Tetra
|
4
|
+
# represents a set of binary dependency packages
|
5
|
+
class Kit
|
6
|
+
include Logging
|
7
|
+
|
8
|
+
def initialize(project)
|
9
|
+
@project = project
|
10
|
+
end
|
11
|
+
|
12
|
+
def items
|
13
|
+
managed_items = maven_kit_items + jar_kit_items
|
14
|
+
|
15
|
+
managed_items + glue_kit_items(managed_items)
|
16
|
+
end
|
17
|
+
|
18
|
+
def maven_kit_items
|
19
|
+
@project.from_directory(File.join("kit", "m2")) do
|
20
|
+
files_in_dir = {}
|
21
|
+
poms = []
|
22
|
+
Find.find(".") do |file|
|
23
|
+
dir = File.dirname(file)
|
24
|
+
if files_in_dir.key?(dir)
|
25
|
+
files_in_dir[dir] << file
|
26
|
+
else
|
27
|
+
files_in_dir[dir] = [file]
|
28
|
+
end
|
29
|
+
|
30
|
+
if file =~ /\.pom$/
|
31
|
+
log.debug "pom found in #{file}"
|
32
|
+
poms << file
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
poms.map do |pom|
|
37
|
+
Tetra::MavenKitItem.new(@project, pom, files_in_dir[File.dirname(pom)])
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def jar_kit_items
|
43
|
+
@project.from_directory(File.join("kit", "jars")) do
|
44
|
+
Pathname.new(".").children.select do |child|
|
45
|
+
child.to_s =~ /.jar$/
|
46
|
+
end.sort.map do |jar|
|
47
|
+
Tetra::JarKitItem.new(@project, jar)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def glue_kit_items(managed_items)
|
53
|
+
managed_files = managed_items.map do |item|
|
54
|
+
item.source_paths.map do |e|
|
55
|
+
Pathname.new(File.join(item.source_dir, e)).cleanpath
|
56
|
+
end
|
57
|
+
end.flatten
|
58
|
+
|
59
|
+
unmanaged_files = []
|
60
|
+
|
61
|
+
@project.from_directory do
|
62
|
+
Find.find("kit") do |file|
|
63
|
+
pathname = Pathname.new(file)
|
64
|
+
if !managed_files.include?(pathname) && !File.directory?(pathname)
|
65
|
+
unmanaged_files << pathname.relative_path_from(Pathname.new("kit"))
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
[Tetra::GlueKitItem.new(@project, unmanaged_files)]
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
module Tetra
|
4
|
+
# represents a prebuilt package dependency from a Maven local repo
|
5
|
+
# in a kit
|
6
|
+
class MavenKitItem
|
7
|
+
# implement to_spec
|
8
|
+
include SpecGenerator
|
9
|
+
attr_reader :project
|
10
|
+
attr_reader :package_name
|
11
|
+
attr_reader :spec_dir
|
12
|
+
attr_reader :template_spec_name
|
13
|
+
attr_reader :conflicts
|
14
|
+
|
15
|
+
# implement to_archive
|
16
|
+
include Archiver
|
17
|
+
attr_reader :source_dir
|
18
|
+
attr_reader :source_paths
|
19
|
+
attr_reader :destination_dir
|
20
|
+
|
21
|
+
# template-specific attributes
|
22
|
+
attr_reader :provides_symbol
|
23
|
+
attr_reader :provides_version
|
24
|
+
attr_reader :install_dir
|
25
|
+
|
26
|
+
def initialize(project, pom, source_paths)
|
27
|
+
path, _ = path_split(pom)
|
28
|
+
rest, version = path_split(path)
|
29
|
+
group_directory, artifact_id = path_split(rest)
|
30
|
+
group_id = path_to_group(group_directory)
|
31
|
+
|
32
|
+
@project = project
|
33
|
+
@package_name = "kit-item-#{group_id.gsub(".", "-")}-#{artifact_id}-#{version}"
|
34
|
+
@spec_dir = "kit"
|
35
|
+
@template_spec_name = "kit_item.spec"
|
36
|
+
@conflicts = false
|
37
|
+
|
38
|
+
@provides_symbol = "tetra-mvn(#{group_id}:#{artifact_id})"
|
39
|
+
@provides_version = version
|
40
|
+
@install_dir = "m2"
|
41
|
+
|
42
|
+
@source_dir = File.join("kit", "m2")
|
43
|
+
@source_paths = source_paths
|
44
|
+
@destination_dir = @package_name
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
|
49
|
+
# splits a path string into a [head, tail] string couple
|
50
|
+
def path_split(path)
|
51
|
+
Pathname.new(path).split.map { |e| e.to_s }
|
52
|
+
end
|
53
|
+
|
54
|
+
# transforms a path into a Maven group
|
55
|
+
def path_to_group(path)
|
56
|
+
splits = path_split(path)
|
57
|
+
if splits[0] == "."
|
58
|
+
return splits[1]
|
59
|
+
else
|
60
|
+
return "#{path_to_group(splits[0])}.#{splits[1]}"
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
module Tetra
|
4
|
+
# represents a Java project package in Tetra, corresponding to a directory
|
5
|
+
# in src/
|
6
|
+
class Package
|
7
|
+
extend Forwardable
|
8
|
+
include SpecGenerator
|
9
|
+
|
10
|
+
attr_reader :name
|
11
|
+
|
12
|
+
def_delegator :@project, :name, :project_name
|
13
|
+
|
14
|
+
def_delegator :@kit, :items, :kit_items
|
15
|
+
|
16
|
+
def_delegator :@pom, :license_name, :license
|
17
|
+
def_delegator :@pom, :url
|
18
|
+
def_delegator :@pom, :group_id
|
19
|
+
def_delegator :@pom, :artifact_id
|
20
|
+
def_delegator :@pom, :version
|
21
|
+
def_delegator :@pom, :runtime_dependency_ids
|
22
|
+
|
23
|
+
# implement to_archive
|
24
|
+
include Archiver
|
25
|
+
attr_reader :source_dir
|
26
|
+
attr_reader :source_paths
|
27
|
+
attr_reader :destination_dir
|
28
|
+
|
29
|
+
def initialize(project, name, pom_path = nil, filter = nil)
|
30
|
+
@project = project
|
31
|
+
@kit = Tetra::Kit.new(project)
|
32
|
+
@name = name
|
33
|
+
@pom = pom_path.nil? ? nil : Tetra::Pom.new(pom_path)
|
34
|
+
@filter = filter
|
35
|
+
|
36
|
+
@source_dir = File.join("src", name)
|
37
|
+
@source_paths = ["*"]
|
38
|
+
@destination_dir = name
|
39
|
+
end
|
40
|
+
|
41
|
+
# a short summary from the POM
|
42
|
+
def summary
|
43
|
+
cleanup_description(@pom.description, 60)
|
44
|
+
end
|
45
|
+
|
46
|
+
# a long summary from the POM
|
47
|
+
def description
|
48
|
+
cleanup_description(@pom.description, 1500)
|
49
|
+
end
|
50
|
+
|
51
|
+
# files produced by this package
|
52
|
+
def outputs
|
53
|
+
@project.get_produced_files(@name).select do |file|
|
54
|
+
File.fnmatch?(@filter, File.basename(file))
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def cleanup_description(raw, max_length)
|
59
|
+
raw
|
60
|
+
.gsub(/[\s]+/, " ")
|
61
|
+
.strip
|
62
|
+
.slice(0..max_length - 1)
|
63
|
+
.sub(/\s\w+$/, "")
|
64
|
+
.sub(/\.+$/, "")
|
65
|
+
end
|
66
|
+
|
67
|
+
# needed by SpecGenerator
|
68
|
+
attr_reader :project
|
69
|
+
|
70
|
+
def package_name
|
71
|
+
name
|
72
|
+
end
|
73
|
+
|
74
|
+
def spec_dir
|
75
|
+
File.join("src", name)
|
76
|
+
end
|
77
|
+
|
78
|
+
def template_spec_name
|
79
|
+
"package.spec"
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
data/lib/tetra/project.rb
CHANGED
@@ -61,19 +61,26 @@ module Tetra
|
|
61
61
|
Dir.chdir(dir) do
|
62
62
|
Tetra::Git.new(".").init
|
63
63
|
|
64
|
-
FileUtils.mkdir_p
|
65
|
-
FileUtils.mkdir_p
|
64
|
+
FileUtils.mkdir_p("src")
|
65
|
+
FileUtils.mkdir_p("kit")
|
66
66
|
|
67
67
|
# populate the project with templates and take a snapshot
|
68
68
|
project = Project.new(".")
|
69
69
|
|
70
|
-
|
71
|
-
template_manager.copy "output", "."
|
72
|
-
template_manager.copy "kit", "."
|
73
|
-
template_manager.copy "src", "."
|
74
|
-
template_manager.copy "gitignore", ".gitignore"
|
70
|
+
template_path = File.join(File.dirname(__FILE__), "..", "template")
|
75
71
|
|
76
|
-
|
72
|
+
templates = {
|
73
|
+
"output" => ".",
|
74
|
+
"kit" => ".",
|
75
|
+
"src" => ".",
|
76
|
+
"gitignore" => ".gitignore"
|
77
|
+
}
|
78
|
+
|
79
|
+
templates.each do |source, destination|
|
80
|
+
FileUtils.cp_r(File.join(template_path, source), destination)
|
81
|
+
end
|
82
|
+
|
83
|
+
project.take_snapshot("Template files added", :init)
|
77
84
|
end
|
78
85
|
end
|
79
86
|
|
@@ -83,7 +90,7 @@ module Tetra
|
|
83
90
|
def dry_run
|
84
91
|
return false if dry_running?
|
85
92
|
|
86
|
-
current_directory = Pathname.new(Dir.pwd).relative_path_from
|
93
|
+
current_directory = Pathname.new(Dir.pwd).relative_path_from(Pathname.new(@full_path))
|
87
94
|
|
88
95
|
take_snapshot("Dry-run started", :dry_run_started, current_directory)
|
89
96
|
true
|
@@ -103,11 +110,11 @@ module Tetra
|
|
103
110
|
@git.revert_whole_directory(".", latest_tag(:dry_run_started))
|
104
111
|
@git.delete_tag(latest_tag(:dry_run_started))
|
105
112
|
else
|
106
|
-
take_snapshot
|
113
|
+
take_snapshot("Changes during dry-run", :dry_run_changed)
|
107
114
|
|
108
115
|
@git.revert_whole_directory("src", latest_tag(:dry_run_started))
|
109
116
|
|
110
|
-
take_snapshot
|
117
|
+
take_snapshot("Dry run finished", :dry_run_finished)
|
111
118
|
end
|
112
119
|
return true
|
113
120
|
end
|
@@ -115,16 +122,8 @@ module Tetra
|
|
115
122
|
end
|
116
123
|
|
117
124
|
# takes a revertable snapshot of this project
|
118
|
-
def take_snapshot(message, tag_prefix
|
119
|
-
|
120
|
-
if tag_prefix
|
121
|
-
"#{tag_prefix}_#{latest_tag_count(tag_prefix) + 1}"
|
122
|
-
else
|
123
|
-
nil
|
124
|
-
end
|
125
|
-
)
|
126
|
-
|
127
|
-
@git.commit_whole_directory(message, tag, tag_message)
|
125
|
+
def take_snapshot(message, tag_prefix, tag_message = nil)
|
126
|
+
@git.commit_whole_directory(message, next_tag(tag_prefix), tag_message)
|
128
127
|
end
|
129
128
|
|
130
129
|
# replaces content in path with new_content, takes a snapshot using
|
@@ -144,7 +143,7 @@ module Tetra
|
|
144
143
|
|
145
144
|
File.open(path, "w") { |io| io.write(new_content) }
|
146
145
|
log.debug "taking snapshot with new content: #{snapshot_message}"
|
147
|
-
|
146
|
+
@git.commit_file(path, snapshot_message, next_tag(tag_prefix))
|
148
147
|
|
149
148
|
if already_existing
|
150
149
|
if previous_tag == ""
|
@@ -172,6 +171,11 @@ module Tetra
|
|
172
171
|
@git.get_tag_maximum_suffix(prefix)
|
173
172
|
end
|
174
173
|
|
174
|
+
# returns the next tag for a given tag prefix
|
175
|
+
def next_tag(prefix)
|
176
|
+
"#{prefix}_#{latest_tag_count(prefix) + 1}"
|
177
|
+
end
|
178
|
+
|
175
179
|
# runs a block from the project directory or a subdirectory
|
176
180
|
def from_directory(subdirectory = "")
|
177
181
|
Dir.chdir(File.join(@full_path, subdirectory)) do
|