gjp 0.11.1 → 0.11.2

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.
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- gjp (0.10.2)
4
+ gjp (0.11.2)
5
5
  clamp
6
6
  json
7
7
  nokogiri
@@ -2,16 +2,9 @@
2
2
  require "gjp/logger"
3
3
  require "clamp"
4
4
 
5
- # Initialize global logger for CLI
6
- Gjp.logger = ::Logger.new(STDERR)
7
- Gjp.logger.datetime_format = "%Y-%m-%d %H:%M "
8
- Gjp.logger.level = ::Logger::ERROR
9
- Gjp.logger.formatter = proc do |severity, datetime, progname, msg|
10
- "#{severity.chars.first}: #{msg}\n"
11
- end
12
-
13
5
  module Gjp
14
6
  class MainCommand < Clamp::Command
7
+ include Logger
15
8
 
16
9
  # Common logging options
17
10
  option ["-v", "--verbose"], :flag, "verbose output"
@@ -32,13 +25,13 @@ module Gjp
32
25
 
33
26
  def configure_log_level(v, vv, vvv)
34
27
  if vvv
35
- Gjp.logger.level = Logger::DEBUG
28
+ log.level = ::Logger::DEBUG
36
29
  elsif vv
37
- Gjp.logger.level = Logger::INFO
30
+ log.level = ::Logger::INFO
38
31
  elsif v
39
- Gjp.logger.level = Logger::WARN
32
+ log.level = ::Logger::WARN
40
33
  else
41
- Gjp.logger.level = Logger::ERROR
34
+ log.level = ::Logger::ERROR
42
35
  end
43
36
  end
44
37
 
@@ -46,38 +39,36 @@ module Gjp
46
39
  subcommand "init", "Inits a gjp project in the current directory" do
47
40
  def execute
48
41
  Gjp::Project.init(".")
49
- puts "Project inited."
50
- puts "Use \"gjp gather\" before adding files to have gjp track them."
42
+ puts "Project inited, now gathering."
43
+ puts "Any file added to kit/ will be added to the kit package."
44
+ puts "Any file added to src/<orgId_artifactId_version> will be added to the corresponding package."
45
+ puts "Note that .gitignore files are honored!"
46
+ puts "When you are ready to test a dry-run build, use \"gjp dry-run\"."
51
47
  end
52
48
  end
53
49
 
54
50
  subcommand "gather", "Starts a gathering phase, add source and kit files to project" do
55
51
  def execute
56
- result = Gjp::Project.new(".").gather
57
- if result == :done
52
+ if Gjp::Project.new(".").gather
58
53
  puts "Now gathering."
59
54
  puts "Any file added to kit/ will be added to the kit package."
60
55
  puts "Any file added to src/<orgId_artifactId_version> will be added to the corresponding package."
61
56
  puts "Note that .gitignore files are honored!"
62
- puts "To finalize this gathering, use \"gjp finish\"."
63
- else
64
- puts "Cannot begin gathering while #{result}, use \"gjp finish\" first."
57
+ puts "When you are ready to test a dry-run build, use \"gjp dry-run\"."
65
58
  end
66
59
  end
67
60
  end
68
61
 
69
62
  subcommand "dry-run", "Starts a dry-run phase, attempt build to add dependencies to kit." do
70
63
  def execute
71
- result = Gjp::Project.new(".").dry_run
72
- if result == :done
64
+ if Gjp::Project.new(".").dry_run
73
65
  puts "Now dry-running, please start your build."
74
66
  puts "Any file added to kit/, presumably downloaded dependencies, will be added to the kit package."
75
67
  puts "The src/ directory and all files in it will be brought back to the current state when finished."
76
68
  puts "Note that .gitignore files are honored!"
77
69
  puts "To run a Maven from the kit, use \"gjp mvn\"."
70
+ puts "To add or remove files, use \"gjp gather\"."
78
71
  puts "To finalize this dry run, use \"gjp finish\"."
79
- else
80
- puts "Cannot begin a dry run while #{result}, use \"gjp finish\" first."
81
72
  end
82
73
  end
83
74
  end
@@ -96,6 +87,11 @@ module Gjp
96
87
  end
97
88
  end
98
89
 
90
+ subcommand "status", "Prints the current phase" do
91
+ def execute
92
+ puts "Now #{Gjp::Project.new(".").get_status.to_s}"
93
+ end
94
+ end
99
95
 
100
96
  subcommand "finish", "Finishes the current phase" do
101
97
  def execute
@@ -136,14 +132,14 @@ module Gjp
136
132
  subcommand "get-pom", "Retrieves a pom corresponding to a filename" do
137
133
  parameter "NAME", "a jar file path, a project directory path or a non-existing filename in the `project-version` form"
138
134
  def execute
139
- puts Gjp::PomGetter.get_pom(name)
135
+ puts Gjp::PomGetter.new.get_pom(name)
140
136
  end
141
137
  end
142
138
 
143
139
  subcommand "get-parent-pom", "Retrieves a pom that is the parent of an existing pom" do
144
140
  parameter "POM", "a pom file path or URI"
145
141
  def execute
146
- puts Gjp::ParentPomGetter.get_parent_pom(pom)
142
+ puts Gjp::ParentPomGetter.new.get_parent_pom(pom)
147
143
  end
148
144
  end
149
145
 
@@ -151,7 +147,7 @@ module Gjp
151
147
  parameter "POM", "a pom file path or URI"
152
148
 
153
149
  def execute
154
- puts Gjp::SourceAddressGetter.get_source_address(pom)
150
+ puts Gjp::SourceAddressGetter.new.get_source_address(pom)
155
151
  end
156
152
  end
157
153
 
@@ -161,7 +157,7 @@ module Gjp
161
157
  parameter "[DIRECTORY]", "directory in which to save the source code", :default => "."
162
158
 
163
159
  def execute
164
- puts Gjp::SourceGetter.get_source(address, pom, directory)
160
+ puts Gjp::SourceGetter.new.get_source(address, pom, directory)
165
161
  end
166
162
  end
167
163
 
@@ -7,9 +7,7 @@ module Gjp
7
7
  # assumes the project is in a directory with jar files
8
8
  # in its (possibly nested) subdirectories
9
9
  class JarTable
10
- def log
11
- Gjp.logger
12
- end
10
+ include Logger
13
11
 
14
12
  attr_reader :rows, :runtime_required_packages, :source_defined_packages
15
13
 
@@ -6,9 +6,7 @@ module Gjp
6
6
  # encapsulates a Linux user that cannot access the Internet
7
7
  # assumes root access (sudo) and iptables are available
8
8
  class LimitedNetworkUser
9
- def log
10
- Gjp.logger
11
- end
9
+ include Logger
12
10
 
13
11
  def initialize(name)
14
12
  @name = name
@@ -3,15 +3,25 @@
3
3
  require "logger"
4
4
 
5
5
  module Gjp
6
- def self.logger=(logger)
7
- @logger = logger
8
- end
6
+ module Logger
7
+ @@logger = nil
9
8
 
10
- def self.logger
11
- @logger ||= Logger.new('/dev/null')
12
- end
9
+ # returns a logger instance
10
+ def self.log
11
+ if @@logger == nil
12
+ @@logger = ::Logger.new(STDERR)
13
+ @@logger.datetime_format = "%Y-%m-%d %H:%M "
14
+ @@logger.level = ::Logger::ERROR
15
+ @@logger.formatter = proc do |severity, datetime, progname, msg|
16
+ "#{severity.chars.first}: #{msg}\n"
17
+ end
18
+ end
19
+ @@logger
20
+ end
13
21
 
14
- def logger
15
- Gjp.logger
22
+ # convenience instance method
23
+ def log
24
+ Gjp::Logger.log
25
+ end
16
26
  end
17
27
  end
@@ -6,9 +6,7 @@ require 'pathname'
6
6
  module Gjp
7
7
  # runs Maven from a gjp kit with gjp-specific options
8
8
  class MavenRunner
9
- def log
10
- Gjp.logger
11
- end
9
+ include Logger
12
10
 
13
11
  def initialize(project)
14
12
  @project = project
@@ -5,9 +5,7 @@ require "text"
5
5
  module Gjp
6
6
  # Facade to search.maven.org
7
7
  class MavenWebsite
8
- def log
9
- Gjp.logger
10
- end
8
+ include Logger
11
9
 
12
10
  # returns a search result object from search.maven.com
13
11
  # searching by a jar sha1 hash
@@ -5,13 +5,10 @@ require "pathname"
5
5
  module Gjp
6
6
  # attempts to get a pom's parent pom
7
7
  class ParentPomGetter
8
-
9
- def self.log
10
- Gjp.logger
11
- end
8
+ include Logger
12
9
 
13
10
  # returns the pom's parent, if any
14
- def self.get_parent_pom(filename)
11
+ def get_parent_pom(filename)
15
12
  begin
16
13
  pom = Pom.new(filename)
17
14
  site = MavenWebsite.new
@@ -11,18 +11,15 @@ require "gjp/version_matcher"
11
11
  module Gjp
12
12
  # attempts to get java projects' pom file
13
13
  class PomGetter
14
-
15
- def self.log
16
- Gjp.logger
17
- end
14
+ include Logger
18
15
 
19
16
  # returns the pom corresponding to a filename
20
- def self.get_pom(filename)
17
+ def get_pom(filename)
21
18
  (get_pom_from_dir(filename) or get_pom_from_jar(filename) or get_pom_from_sha1(filename) or get_pom_from_heuristic(filename))
22
19
  end
23
20
 
24
21
  # returns the pom in a project directory
25
- def self.get_pom_from_dir(dir)
22
+ def get_pom_from_dir(dir)
26
23
  if File.directory?(dir)
27
24
  pom_path = File.join(dir, "pom.xml")
28
25
  if File.file?(pom_path)
@@ -33,7 +30,7 @@ module Gjp
33
30
  end
34
31
 
35
32
  # returns a pom embedded in a jar file
36
- def self.get_pom_from_jar(file)
33
+ def get_pom_from_jar(file)
37
34
  begin
38
35
  Zip::ZipFile.foreach(file) do |entry|
39
36
  if entry.name =~ /\/pom.xml$/
@@ -50,7 +47,7 @@ module Gjp
50
47
  end
51
48
 
52
49
  # returns a pom from search.maven.org with a jar sha1 search
53
- def self.get_pom_from_sha1(file)
50
+ def get_pom_from_sha1(file)
54
51
  begin
55
52
  if File.file?(file)
56
53
  site = MavenWebsite.new
@@ -70,18 +67,19 @@ module Gjp
70
67
  end
71
68
 
72
69
  # returns a pom from search.maven.org with a heuristic name search
73
- def self.get_pom_from_heuristic(filename)
70
+ def get_pom_from_heuristic(filename)
74
71
  begin
75
72
  site = MavenWebsite.new
76
73
  filename = Pathname.new(filename).basename.to_s.sub(/.jar$/, "")
77
- my_artifact_id, my_version = VersionMatcher.split_version(filename)
74
+ version_matcher = VersionMatcher.new
75
+ my_artifact_id, my_version = version_matcher.split_version(filename)
78
76
 
79
77
  result = site.search_by_name(my_artifact_id).first
80
78
  if result != nil
81
79
  group_id, artifact_id, version = site.get_maven_id_from result
82
80
  results = site.search_by_group_id_and_artifact_id(group_id, artifact_id)
83
81
  their_versions = results.map {|doc| doc["v"]}
84
- best_matched_version = if my_version != nil then VersionMatcher.best_match(my_version, their_versions) else their_versions.max end
82
+ best_matched_version = if my_version != nil then version_matcher.best_match(my_version, their_versions) else their_versions.max end
85
83
  best_matched_result = (results.select{|result| result["v"] == best_matched_version}).first
86
84
 
87
85
  group_id, artifact_id, version = site.get_maven_id_from(best_matched_result)
@@ -5,9 +5,10 @@ require 'find'
5
5
  module Gjp
6
6
  # encapsulates a Gjp project directory
7
7
  class Project
8
- def log
9
- Gjp.logger
10
- end
8
+ include Logger
9
+
10
+ # list of possible statuses
11
+ @@statuses = [:gathering, :dry_running]
11
12
 
12
13
  attr_accessor :full_path
13
14
 
@@ -37,38 +38,43 @@ module Gjp
37
38
  # inits a new project directory structure
38
39
  def self.init(dir)
39
40
  Dir.chdir(dir) do
40
- `git init`
41
-
42
- Dir.mkdir("src")
43
- File.open(File.join("src", "README"), "w") do |file|
44
- file.puts "Sources are to be placed in subdirectories named after Maven names: orgId_artifactId_version"
45
- end
46
- Dir.mkdir("kit")
47
- File.open(File.join("kit", "README"), "w") do |file|
48
- file.puts "Build tool binaries are to be placed here"
41
+ if Dir.exists?(".git") == false
42
+ `git init`
49
43
  end
50
44
 
45
+ copy_from_template "file_lists", "."
46
+ copy_from_template "src", "."
47
+ copy_from_template "kit", "."
48
+
51
49
  `git add .`
52
50
  `git commit -m "Project initialized"`
53
- `git tag init`
51
+
52
+ # automatically begin a gathering phase
53
+ Project.new(".").gather
54
54
  end
55
55
  end
56
56
 
57
+ # copies a file/dir from the template directory to the destination directory
58
+ def self.copy_from_template(template_file, destination_dir)
59
+ FileUtils.cp_r(File.join(File.dirname(__FILE__), "..", "template", template_file), destination_dir)
60
+ end
61
+
57
62
  # starts a gathering phase, all files added to the project
58
63
  # will be added to packages (including kit)
59
64
  def gather
60
65
  from_directory do
61
- if get_status(:gathering)
62
- return :gathering
63
- elsif get_status(:dry_running)
64
- return :dry_running
66
+ status = get_status
67
+ if status == :gathering
68
+ return false
69
+ elsif status == :dry_running
70
+ finish
65
71
  end
66
72
 
67
- set_status(:gathering)
68
- commit_all("Gathering started")
73
+ set_status :gathering
74
+ take_snapshot "Gathering started", :revertable
69
75
  end
70
76
 
71
- :done
77
+ true
72
78
  end
73
79
 
74
80
  # starts a dry running phase: files added to the kit will
@@ -76,46 +82,48 @@ module Gjp
76
82
  # end
77
83
  def dry_run
78
84
  from_directory do
79
- if get_status(:gathering)
80
- return :gathering
81
- elsif get_status(:dry_running)
82
- return :dry_running
85
+ status = get_status
86
+ if status == :dry_running
87
+ return false
88
+ elsif status == :gathering
89
+ finish
83
90
  end
84
91
 
85
- set_status(:dry_running)
86
- commit_all("Dry-run started")
92
+ set_status :dry_running
93
+ take_snapshot "Dry-run started", :revertable
87
94
  end
88
95
 
89
- :done
96
+ true
90
97
  end
91
98
 
92
99
  # ends any phase that was previously started,
93
100
  # generating file lists
94
101
  def finish
95
102
  from_directory do
96
- if get_status(:gathering)
97
- commit_all("Changes during gathering")
103
+ status = get_status
104
+ if status == :gathering
105
+ take_snapshot "Changes during gathering"
98
106
 
99
- update_changed_file_list("kit", "gjp_kit_file_list")
100
- update_changed_src_file_list(:file_list)
101
- commit_all("File list updates")
107
+ update_changed_file_list("kit", "kit")
108
+ update_changed_src_file_list(:input)
109
+ take_snapshot "File list updates"
102
110
 
103
- clear_status(:gathering)
104
- commit_all("Gathering finished")
111
+ set_status nil
112
+ take_snapshot "Gathering finished", :revertable
105
113
 
106
114
  :gathering
107
- elsif get_status(:dry_running)
108
- commit_all("Changes during dry-run")
115
+ elsif status == :dry_running
116
+ take_snapshot "Changes during dry-run"
109
117
 
110
- update_changed_file_list("kit", "gjp_kit_file_list")
111
- update_changed_src_file_list(:produced_file_list)
112
- commit_all("File list updates")
118
+ update_changed_file_list("kit", "kit")
119
+ update_changed_src_file_list(:output)
120
+ take_snapshot "File list updates"
113
121
 
114
- revert("src", 2)
115
- commit_all("Sources reverted as before dry-run")
122
+ revert("src")
123
+ take_snapshot "Sources reverted as before dry-run"
116
124
 
117
- clear_status(:dry_running)
118
- commit_all("Dry run finished")
125
+ set_status nil
126
+ take_snapshot "Dry run finished", :revertable
119
127
 
120
128
  :dry_running
121
129
  end
@@ -124,84 +132,103 @@ module Gjp
124
132
 
125
133
  def update_changed_src_file_list(list_name)
126
134
  Dir.foreach("src") do |entry|
127
- if File.directory?(File.join(Dir.getwd, "src", entry)) and entry =~ /([^_\/]+_[^_]+_[^_]+)$/
128
- update_changed_file_list(File.join("src", entry), "gjp_#{$1}_#{list_name.to_s}")
135
+ if File.directory?(File.join(Dir.getwd, "src", entry)) and entry =~ /([^:\/]+:[^:]+:[^:]+)$/
136
+ update_changed_file_list(File.join("src", entry), "#{$1}_#{list_name.to_s}")
129
137
  end
130
138
  end
131
139
  end
132
140
 
133
- def update_changed_file_list(directory, list_file)
134
- existing_files = if File.exists?(list_file)
141
+ def update_changed_file_list(directory, file_name)
142
+ list_file = File.join("file_lists", file_name)
143
+ tracked_files = if File.exists?(list_file)
135
144
  File.readlines(list_file)
136
145
  else
137
146
  []
138
147
  end
139
148
 
140
- files = (
149
+ new_tracked_files = (
141
150
  `git diff-tree --no-commit-id --name-only -r HEAD`.split("\n")
142
151
  .select { |file| file.start_with?(directory) }
143
152
  .map { |file|file[directory.length + 1, file.length] }
144
- .concat(existing_files)
153
+ .concat(tracked_files)
145
154
  .sort
146
155
  .uniq
147
156
  )
148
157
 
149
- log.debug("writing file list for #{directory}: #{files.to_s}")
158
+ log.debug("writing file list for #{directory}: #{new_tracked_files.to_s}")
150
159
 
151
160
 
152
161
  File.open(list_file, "w+") do |file_list|
153
- files.each do |file|
162
+ new_tracked_files.each do |file|
154
163
  file_list.puts file
155
164
  end
156
165
  end
157
166
  end
158
167
 
159
168
  # adds the project's whole contents to git
160
- def commit_all(message)
161
- Find.find(".") do |path|
162
- if path =~ /.gitignore$/
163
- puts "Deleting #{path} to preserve all files..."
164
- File.delete(path)
165
- end
166
- end
167
-
169
+ # if tag is given, commit is tagged
170
+ def take_snapshot(message, revertability = :not_revertable)
168
171
  log.debug "committing with message: #{message}"
169
172
 
170
173
  `git rm -r --cached .`
171
174
  `git add .`
172
175
  `git commit -m "#{message}"`
176
+
177
+ if revertability == :revertable
178
+ latest_count = if latest_snapshot_name =~ /^gjp_revertable_snapshot_([0-9]+)$/
179
+ $1
180
+ else
181
+ 0
182
+ end
183
+ `git tag gjp_revertable_snapshot_#{$1.to_i + 1}`
184
+ end
185
+ end
186
+
187
+ # returns the last snapshot git tag name
188
+ def latest_snapshot_name
189
+ `git describe --abbrev=0 --tags --match=gjp_revertable_snapshot_*`.strip
173
190
  end
174
191
 
175
192
  # reverts dir contents as commit_count commits ago
176
- def revert(dir, commit_count)
193
+ def revert(dir)
177
194
  `git rm -rf --ignore-unmatch #{dir}`
178
- `git checkout -f HEAD~#{commit_count} -- #{dir}`
195
+ `git checkout -f #{latest_snapshot_name} -- #{dir}`
179
196
 
180
197
  `git clean -f -d #{dir}`
181
198
  end
182
199
 
183
- # gets a project status flag
184
- def get_status(status)
185
- file_name = status_file_name(status)
186
- File.exists?(file_name)
187
- end
188
-
189
- # sets a project status flag
190
- def set_status(status)
191
- file_name = status_file_name(status)
192
- if File.exists?(file_name) == false
193
- FileUtils.touch(file_name)
200
+ # returns a symbol with the current status
201
+ # flag
202
+ def get_status
203
+ from_directory do
204
+ @@statuses.each do |status|
205
+ if File.exists?(status_file_name(status))
206
+ return status
207
+ end
208
+ end
194
209
  end
210
+
211
+ nil
195
212
  end
196
213
 
197
- # sets a project status flag
198
- def clear_status(status)
199
- file_name = status_file_name(status)
200
- if File.exists?(file_name)
201
- File.delete(file_name)
214
+ # sets a project status flag. if status = nil,
215
+ # clears all status flags
216
+ def set_status(status)
217
+ from_directory do
218
+ @@statuses.each do |a_status|
219
+ file_name = status_file_name(a_status)
220
+ if File.exists?(file_name)
221
+ File.delete(file_name)
222
+ end
223
+
224
+ if a_status == status
225
+ FileUtils.touch(file_name)
226
+ end
227
+ end
202
228
  end
203
229
  end
204
230
 
231
+ # returns a file name that represents a status
205
232
  def status_file_name(status)
206
233
  ".#{status.to_s}"
207
234
  end