tetra 0.40.0 → 0.41.0

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.
Files changed (40) hide show
  1. data/.gitignore +1 -1
  2. data/Gemfile +2 -0
  3. data/Gemfile.lock +48 -0
  4. data/MOTIVATION.md +9 -3
  5. data/README.md +5 -5
  6. data/SPECIAL_CASES.md +1 -3
  7. data/integration-tests/{commons.sh → build-commons.sh} +26 -6
  8. data/integration-tests/build-obs.sh +21 -0
  9. data/lib/template/kit_item.spec +53 -0
  10. data/lib/template/package.spec +4 -2
  11. data/lib/tetra.rb +5 -3
  12. data/lib/tetra/archiver.rb +23 -87
  13. data/lib/tetra/commands/generate_all.rb +13 -16
  14. data/lib/tetra/commands/generate_kit_archive.rb +4 -4
  15. data/lib/tetra/commands/generate_kit_spec.rb +4 -2
  16. data/lib/tetra/commands/generate_package_archive.rb +1 -1
  17. data/lib/tetra/commands/generate_package_spec.rb +2 -2
  18. data/lib/tetra/git.rb +19 -10
  19. data/lib/tetra/glue_kit_item.rb +42 -0
  20. data/lib/tetra/jar_kit_item.rb +45 -0
  21. data/lib/tetra/kit.rb +73 -0
  22. data/lib/tetra/maven_kit_item.rb +64 -0
  23. data/lib/tetra/package.rb +82 -0
  24. data/lib/tetra/project.rb +26 -22
  25. data/lib/tetra/spec_generator.rb +38 -42
  26. data/lib/tetra/version.rb +1 -1
  27. data/spec/lib/archiver_spec.rb +30 -86
  28. data/spec/lib/git_spec.rb +8 -8
  29. data/spec/lib/glue_kit_item_spec.rb +31 -0
  30. data/spec/lib/kit_spec.rb +67 -0
  31. data/spec/lib/maven_kit_item_spec.rb +74 -0
  32. data/spec/lib/package_spec.rb +78 -0
  33. data/spec/lib/project_spec.rb +1 -1
  34. data/spec/lib/spec_generator_spec.rb +59 -87
  35. metadata +15 -8
  36. data/lib/template/kit.spec +0 -64
  37. data/lib/tetra/kit_spec_adapter.rb +0 -28
  38. data/lib/tetra/package_spec_adapter.rb +0 -59
  39. data/lib/tetra/template_manager.rb +0 -33
  40. 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
- result_path = Tetra::Archiver.new(project).archive_kit(whole?)
13
- print_generation_result(project, result_path)
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
- result_path, conflict_count = Tetra::SpecGenerator.new(project).generate_kit_spec
11
- print_generation_result(project, result_path, conflict_count)
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::Archiver.new(project).archive_package package_name
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 = Tetra::SpecGenerator.new(project)
16
- .generate_package_spec(package_name, pom, filter)
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 and removes
50
- # all files not in the current directory.
51
- # if tag is given, commit is also tagged
52
- def commit_whole_directory(message, tag = nil, tag_message = nil)
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
- unless tag.nil?
69
- if !tag_message.nil?
70
- `git tag tetra_#{tag} -m "#{tag_message}"`
71
- else
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 "src"
65
- FileUtils.mkdir_p "kit"
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
- template_manager = Tetra::TemplateManager.new
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
- project.take_snapshot "Template files added", :init
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 Pathname.new(@full_path)
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 "Changes during dry-run", :dry_run_changed
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 "Dry run finished", :dry_run_finished
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 = nil, tag_message = nil)
119
- tag = (
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
- take_snapshot(snapshot_message, tag_prefix)
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