rake-deveiate 0.1.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.
- checksums.yaml +7 -0
- checksums.yaml.gz.sig +0 -0
- data/History.md +7 -0
- data/README.md +84 -0
- data/data/rake-deveiate/History.erb +5 -0
- data/data/rake-deveiate/README.erb +64 -0
- data/lib/rake/deveiate/checks.rb +200 -0
- data/lib/rake/deveiate/docs.rb +34 -0
- data/lib/rake/deveiate/gem_dep_finder.rb +97 -0
- data/lib/rake/deveiate/gemspec.rb +177 -0
- data/lib/rake/deveiate/generate.rb +103 -0
- data/lib/rake/deveiate/hg.rb +542 -0
- data/lib/rake/deveiate/packaging.rb +42 -0
- data/lib/rake/deveiate/releases.rb +40 -0
- data/lib/rake/deveiate/specs.rb +30 -0
- data/lib/rake/deveiate.rb +675 -0
- data.tar.gz.sig +0 -0
- metadata +213 -0
- metadata.gz.sig +0 -0
@@ -0,0 +1,103 @@
|
|
1
|
+
# -*- ruby -*-
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require 'erb'
|
5
|
+
|
6
|
+
require 'rake/deveiate' unless defined?( Rake::DevEiate )
|
7
|
+
|
8
|
+
|
9
|
+
# Project-file generation tasks
|
10
|
+
module Rake::DevEiate::Generate
|
11
|
+
|
12
|
+
|
13
|
+
# Template files
|
14
|
+
README_TEMPLATE = 'README.erb'
|
15
|
+
HISTORY_TEMPLATE = 'History.erb'
|
16
|
+
|
17
|
+
# RVM metadata files
|
18
|
+
RUBY_VERSION_FILE = Rake::DevEiate::PROJECT_DIR + '.ruby-version'
|
19
|
+
GEMSET_FILE = Rake::DevEiate::PROJECT_DIR + '.ruby-gemset'
|
20
|
+
|
21
|
+
# Flags to use when opening a file for generation
|
22
|
+
FILE_CREATION_FLAGS = File::WRONLY | File::CREAT | File::EXCL
|
23
|
+
|
24
|
+
|
25
|
+
### Define generation tasks.
|
26
|
+
def define_tasks
|
27
|
+
super if defined?( super )
|
28
|
+
|
29
|
+
file( self.readme_file.to_s )
|
30
|
+
file( self.history_file.to_s )
|
31
|
+
file( self.manifest_file.to_s )
|
32
|
+
file( RUBY_VERSION_FILE.to_s )
|
33
|
+
file( GEMSET_FILE.to_s )
|
34
|
+
|
35
|
+
task( self.readme_file, &method(:do_generate_readme_file) )
|
36
|
+
task( self.history_file, &method(:do_generate_history_file) )
|
37
|
+
task( self.manifest_file, &method(:do_generate_manifest_file) )
|
38
|
+
task( RUBY_VERSION_FILE, &method(:do_generate_ruby_version_file) )
|
39
|
+
task( GEMSET_FILE, &method(:do_generate_gemset_file) )
|
40
|
+
|
41
|
+
task :generate => [
|
42
|
+
self.readme_file,
|
43
|
+
self.history_file,
|
44
|
+
self.manifest_file,
|
45
|
+
RUBY_VERSION_FILE,
|
46
|
+
GEMSET_FILE,
|
47
|
+
]
|
48
|
+
end
|
49
|
+
|
50
|
+
|
51
|
+
|
52
|
+
### Generate a README file if one doesn't already exist. Error if one does.
|
53
|
+
def do_generate_readme_file( task, args )
|
54
|
+
self.generate_from_template( task.name, README_TEMPLATE )
|
55
|
+
end
|
56
|
+
|
57
|
+
|
58
|
+
|
59
|
+
### Generate a History file if one doesn't already exist. Error if one does.
|
60
|
+
def do_generate_history_file( task, args )
|
61
|
+
self.generate_from_template( task.name, HISTORY_TEMPLATE )
|
62
|
+
end
|
63
|
+
|
64
|
+
|
65
|
+
### Generate a manifest with a default set of files listed.
|
66
|
+
def do_generate_manifest_file( task, args )
|
67
|
+
self.prompt.ok "Generating #{task.name}..."
|
68
|
+
File.open( task.name, FILE_CREATION_FLAGS, 0644, encoding: 'utf-8' ) do |io|
|
69
|
+
io.puts( *self.project_files )
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
|
74
|
+
### Generate a file that sets the project's working Ruby version.
|
75
|
+
def do_generate_ruby_version_file( task, args )
|
76
|
+
self.prompt.ok "Generating #{task.name}..."
|
77
|
+
File.open( task.name, FILE_CREATION_FLAGS, 0644, encoding: 'utf-8' ) do |io|
|
78
|
+
io.puts( RUBY_VERSION.sub(/\.\d+$/, '') )
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
|
83
|
+
### Generate a file that sets the project's gemset
|
84
|
+
def do_generate_gemset_file( task, args )
|
85
|
+
self.prompt.ok "Generating #{task.name}..."
|
86
|
+
File.open( task.name, FILE_CREATION_FLAGS, 0644, encoding: 'utf-8' ) do |io|
|
87
|
+
io.puts( self.name )
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
|
92
|
+
### Generate the given +filename+ from the template filed at +template_path+.
|
93
|
+
def generate_from_template( filename, template_path )
|
94
|
+
self.prompt.ok "Generating #{filename}..."
|
95
|
+
File.open( filename, FILE_CREATION_FLAGS, 0644, encoding: 'utf-8' ) do |io|
|
96
|
+
result = self.load_and_render_template( template_path )
|
97
|
+
io.print( result )
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
end # module Rake::DevEiate::Hg
|
102
|
+
|
103
|
+
|
@@ -0,0 +1,542 @@
|
|
1
|
+
# -*- ruby -*-
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require 'tempfile'
|
5
|
+
require 'shellwords'
|
6
|
+
require 'hglib'
|
7
|
+
require 'tty/editor'
|
8
|
+
|
9
|
+
require 'rake/deveiate' unless defined?( Rake::DevEiate )
|
10
|
+
|
11
|
+
|
12
|
+
# Version-control tasks
|
13
|
+
module Rake::DevEiate::Hg
|
14
|
+
|
15
|
+
# The name of the file to edit for the commit message
|
16
|
+
COMMIT_MSG_FILE = Pathname( 'commit-msg.txt' )
|
17
|
+
|
18
|
+
# The name of the ignore file
|
19
|
+
IGNORE_FILE = Rake::DevEiate::PROJECT_DIR + '.hgignore'
|
20
|
+
|
21
|
+
# The prefix to use for release version tags by default
|
22
|
+
DEFAULT_RELEASE_TAG_PREFIX = 'v'
|
23
|
+
|
24
|
+
# Colors for presenting file statuses
|
25
|
+
STATUS_COLORS = {
|
26
|
+
'M' => [:blue], # modified
|
27
|
+
'A' => [:bold, :green], # added
|
28
|
+
'R' => [:bold, :black], # removed
|
29
|
+
'C' => [:white], # clean
|
30
|
+
'!' => [:bold, :white, :on_red], # missing
|
31
|
+
'?' => [:yellow], # not tracked
|
32
|
+
'I' => [:dim, :white], # ignored
|
33
|
+
}
|
34
|
+
|
35
|
+
# File indentation
|
36
|
+
FILE_INDENT = " • "
|
37
|
+
|
38
|
+
|
39
|
+
### Set up defaults
|
40
|
+
def setup( _name, **options )
|
41
|
+
super if defined?( super )
|
42
|
+
|
43
|
+
@release_tag_prefix = options[:release_tag_prefix] || DEFAULT_RELEASE_TAG_PREFIX
|
44
|
+
@sign_tags = options[:sign_tags] || true
|
45
|
+
end
|
46
|
+
|
47
|
+
|
48
|
+
##
|
49
|
+
# The prefix to use for version tags
|
50
|
+
attr_accessor :release_tag_prefix
|
51
|
+
|
52
|
+
##
|
53
|
+
# Boolean: if true, sign tags after creating them
|
54
|
+
attr_accessor :sign_tags
|
55
|
+
|
56
|
+
|
57
|
+
### Define version-control tasks
|
58
|
+
def define_tasks
|
59
|
+
super if defined?( super )
|
60
|
+
|
61
|
+
return unless File.directory?( '.hg' )
|
62
|
+
|
63
|
+
file COMMIT_MSG_FILE.to_s do |task|
|
64
|
+
edit_commit_log( task.name )
|
65
|
+
end
|
66
|
+
|
67
|
+
CLEAN.include( COMMIT_MSG_FILE.to_s )
|
68
|
+
|
69
|
+
namespace :hg do
|
70
|
+
|
71
|
+
desc "Prepare for a new release"
|
72
|
+
task( :prerelease, &method(:do_hg_prerelease) )
|
73
|
+
|
74
|
+
desc "Check for new files and offer to add/ignore/delete them."
|
75
|
+
task( :newfiles, &method(:do_hg_newfiles) )
|
76
|
+
task :add => :newfiles
|
77
|
+
|
78
|
+
desc "Pull and update from the default repo"
|
79
|
+
task( :pull, &method(:do_hg_pull) )
|
80
|
+
|
81
|
+
desc "Pull and update without confirmation"
|
82
|
+
task( :pull_without_confirmation, &method(:do_hg_pull_without_confirmation) )
|
83
|
+
|
84
|
+
desc "Update to tip"
|
85
|
+
task( :update, &method(:do_hg_update) )
|
86
|
+
|
87
|
+
desc "Clobber all changes (hg up -C)"
|
88
|
+
task( :update_and_clobber, &method(:do_hg_update_and_clobber) )
|
89
|
+
|
90
|
+
desc "Mercurial-specific pre-checkin hook"
|
91
|
+
task :precheckin
|
92
|
+
|
93
|
+
desc "Mercurial-specific pre-release hook"
|
94
|
+
task :prerelease => 'hg:check_history'
|
95
|
+
|
96
|
+
desc "Check the current code in if tests pass"
|
97
|
+
task( :checkin => [:pull, :newfiles, :precheckin, COMMIT_MSG_FILE.to_s], &method(:do_hg_checkin) )
|
98
|
+
|
99
|
+
desc "Mercurial-specific post-release hook"
|
100
|
+
task( :postrelease, &method(:do_hg_postrelease) )
|
101
|
+
|
102
|
+
desc "Push to the default origin repo (if there is one)"
|
103
|
+
task( :push, &method(:do_hg_push) )
|
104
|
+
|
105
|
+
desc "Push to the default repo without confirmation"
|
106
|
+
task :push_without_confirmation do |task, args|
|
107
|
+
self.hg.push
|
108
|
+
end
|
109
|
+
|
110
|
+
desc "Check the history file to ensure it contains an entry for each release tag"
|
111
|
+
task( :check_history, &method(:do_hg_check_history) )
|
112
|
+
|
113
|
+
desc "Generate and edit a new version entry in the history file"
|
114
|
+
task( :update_history, &method(:do_hg_update_history) )
|
115
|
+
|
116
|
+
task( :debug, &method(:do_hg_debug) )
|
117
|
+
end
|
118
|
+
|
119
|
+
|
120
|
+
# Hook some generic tasks to the mercurial-specific ones
|
121
|
+
task :ci => 'hg:checkin'
|
122
|
+
|
123
|
+
task :prerelease => 'hg:prerelease'
|
124
|
+
task :precheckin => 'hg:precheckin'
|
125
|
+
task :debug => 'hg:debug'
|
126
|
+
task :postrelease => 'hg:postrelease'
|
127
|
+
|
128
|
+
desc "Update the history file with the changes since the last version tag."
|
129
|
+
task :update_history => 'hg:update_history'
|
130
|
+
|
131
|
+
rescue ::Exception => err
|
132
|
+
$stderr.puts "%s while defining Mercurial tasks: %s" % [ err.class.name, err.message ]
|
133
|
+
raise
|
134
|
+
end
|
135
|
+
|
136
|
+
|
137
|
+
### The body of the hg:prerelease task.
|
138
|
+
def do_hg_prerelease( task, args )
|
139
|
+
uncommitted_files = self.hg.status( n: true )
|
140
|
+
unless uncommitted_files.empty?
|
141
|
+
self.show_file_statuses( uncommitted_files )
|
142
|
+
|
143
|
+
fail unless self.prompt.yes?( "Release anyway?" ) do |q|
|
144
|
+
q.default( false )
|
145
|
+
end
|
146
|
+
|
147
|
+
self.prompt.warn "Okay, releasing with uncommitted versions."
|
148
|
+
end
|
149
|
+
|
150
|
+
pkg_version_tag = self.current_version_tag
|
151
|
+
|
152
|
+
# Look for a tag for the current release version, and if it exists abort
|
153
|
+
if self.hg.tags.find {|tag| tag.name == pkg_version_tag }
|
154
|
+
self.prompt.error "Version #{self.version} already has a tag."
|
155
|
+
fail
|
156
|
+
end
|
157
|
+
|
158
|
+
if self.sign_tags
|
159
|
+
message = "Signing %s" % [ pkg_version_tag ]
|
160
|
+
self.prompt.ok( message )
|
161
|
+
self.hg.sign( message: message )
|
162
|
+
end
|
163
|
+
|
164
|
+
# Tag the current rev
|
165
|
+
rev = self.hg.identify
|
166
|
+
self.prompt.ok "Tagging rev %s as %s" % [ rev, pkg_version_tag ]
|
167
|
+
self.hg.tag( pkg_version_tag )
|
168
|
+
end
|
169
|
+
|
170
|
+
|
171
|
+
### The body of the hg:postrelease task.
|
172
|
+
def do_hg_postrelease( task, args )
|
173
|
+
if self.hg.status( 'checksum', unknown: true ).any?
|
174
|
+
self.prompt.say "Adding release artifacts..."
|
175
|
+
self.hg.add( 'checksum' )
|
176
|
+
self.hg.commit( 'checksum', message: "Adding release checksum." )
|
177
|
+
end
|
178
|
+
|
179
|
+
if self.prompt.yes?( "Move released changesets to public phase?" )
|
180
|
+
self.prompt.say "Publicising changesets..."
|
181
|
+
self.hg.phase( :public )
|
182
|
+
end
|
183
|
+
|
184
|
+
Rake::Take['hg:push'].invoke
|
185
|
+
end
|
186
|
+
|
187
|
+
|
188
|
+
### The body of the hg:newfiles task.
|
189
|
+
def do_hg_newfiles( task, args )
|
190
|
+
self.prompt.say "Checking for new files..."
|
191
|
+
|
192
|
+
entries = self.hg.status( no_status: true, unknown: true )
|
193
|
+
|
194
|
+
unless entries.empty?
|
195
|
+
files_to_add = []
|
196
|
+
files_to_ignore = []
|
197
|
+
files_to_delete = []
|
198
|
+
|
199
|
+
entries.each do |entry|
|
200
|
+
description = " %s: %s" % [ entry.path, entry.status_description ]
|
201
|
+
action = self.prompt.select( description ) do |menu|
|
202
|
+
menu.choice "add", :a
|
203
|
+
menu.choice "ignore", :i
|
204
|
+
menu.choice "skip", :s
|
205
|
+
menu.choice "delete", :d
|
206
|
+
end
|
207
|
+
|
208
|
+
case action
|
209
|
+
when :a
|
210
|
+
files_to_add << entry.path
|
211
|
+
when :i
|
212
|
+
files_to_ignore << entry.path
|
213
|
+
when :d
|
214
|
+
files_to_delete << entry.path
|
215
|
+
end
|
216
|
+
end
|
217
|
+
|
218
|
+
unless files_to_add.empty?
|
219
|
+
self.hg.add( *files_to_add )
|
220
|
+
end
|
221
|
+
|
222
|
+
unless files_to_ignore.empty?
|
223
|
+
hg_ignore_files( *files_to_ignore )
|
224
|
+
end
|
225
|
+
|
226
|
+
unless files_to_delete.empty?
|
227
|
+
delete_extra_files( *files_to_delete )
|
228
|
+
end
|
229
|
+
end
|
230
|
+
end
|
231
|
+
|
232
|
+
|
233
|
+
### The body of the hg:pull task.
|
234
|
+
def do_hg_pull( task, args )
|
235
|
+
paths = self.hg.paths
|
236
|
+
if origin_url = paths[:default]
|
237
|
+
if self.prompt.yes?( "Pull and update from '#{origin_url}'?" )
|
238
|
+
self.hg.pull_update
|
239
|
+
end
|
240
|
+
else
|
241
|
+
trace "Skipping pull: No 'default' path."
|
242
|
+
end
|
243
|
+
end
|
244
|
+
|
245
|
+
|
246
|
+
### The body of the hg:pull_without_confirmation task.
|
247
|
+
def do_hg_pull_without_confirmation( task, args )
|
248
|
+
self.hg.pull
|
249
|
+
end
|
250
|
+
|
251
|
+
|
252
|
+
### The body of the hg:update task.
|
253
|
+
def do_hg_update( task, args )
|
254
|
+
self.hg.pull_update
|
255
|
+
end
|
256
|
+
|
257
|
+
|
258
|
+
### The body of the hg:update_and_clobber task.
|
259
|
+
def do_hg_update_and_clobber( task, args )
|
260
|
+
self.hg.update( clean: true )
|
261
|
+
end
|
262
|
+
|
263
|
+
|
264
|
+
### The body of the checkin task.
|
265
|
+
def do_hg_checkin( task, args )
|
266
|
+
targets = args.extras
|
267
|
+
self.prompt.say( self.pastel.cyan( "---\n", COMMIT_MSG_FILE.read, "---\n" ) )
|
268
|
+
if self.prompt.yes?( "Continue with checkin?" )
|
269
|
+
self.hg.commit( *targets, logfile: COMMIT_MSG_FILE.to_s )
|
270
|
+
rm_f COMMIT_MSG_FILE
|
271
|
+
else
|
272
|
+
abort
|
273
|
+
end
|
274
|
+
Rake::Task[ 'hg:push' ].invoke
|
275
|
+
end
|
276
|
+
|
277
|
+
|
278
|
+
### The body of the push task.
|
279
|
+
def do_hg_push( task, args )
|
280
|
+
paths = self.hg.paths
|
281
|
+
if origin_url = paths[:default]
|
282
|
+
if self.prompt.yes?( "Push to '#{origin_url}'?" ) {|q| q.default(false) }
|
283
|
+
self.hg.push
|
284
|
+
self.prompt.ok "Done."
|
285
|
+
else
|
286
|
+
abort
|
287
|
+
end
|
288
|
+
else
|
289
|
+
trace "Skipping push: No 'default' path."
|
290
|
+
end
|
291
|
+
end
|
292
|
+
|
293
|
+
|
294
|
+
### Check the history file against the list of release tags in the working copy
|
295
|
+
### and ensure there's an entry for each tag.
|
296
|
+
def do_hg_check_history( task, args )
|
297
|
+
unless self.history_file.readable?
|
298
|
+
self.prompt.error "History file is missing or unreadable."
|
299
|
+
abort
|
300
|
+
end
|
301
|
+
|
302
|
+
self.prompt.say "Checking history..."
|
303
|
+
missing_tags = self.get_unhistoried_version_tags
|
304
|
+
|
305
|
+
unless missing_tags.empty?
|
306
|
+
self.prompt.error "%s needs updating; missing entries for tags: %s" %
|
307
|
+
[ self.history_file, missing_tags.join(', ') ]
|
308
|
+
abort
|
309
|
+
end
|
310
|
+
end
|
311
|
+
|
312
|
+
|
313
|
+
### Generate a new history file entry for the current version.
|
314
|
+
def do_hg_update_history( task, args ) # Needs refactoring
|
315
|
+
unless self.history_file.readable?
|
316
|
+
self.prompt.error "History file is missing or unreadable."
|
317
|
+
abort
|
318
|
+
end
|
319
|
+
|
320
|
+
version_tag = self.current_version_tag
|
321
|
+
previous_tag = self.previous_version_tag
|
322
|
+
self.prompt.say "Updating history for %s..." % [ version_tag ]
|
323
|
+
|
324
|
+
if self.get_history_file_versions.include?( version_tag )
|
325
|
+
self.log.ok "History file already includes a section for %s" % [ version_tag ]
|
326
|
+
abort
|
327
|
+
end
|
328
|
+
|
329
|
+
header, rest = self.history_file.read( encoding: 'utf-8' ).
|
330
|
+
split( /(?<=^---)/m, 2 )
|
331
|
+
|
332
|
+
self.trace "Rest is: %p" % [ rest ]
|
333
|
+
if !rest || rest.empty?
|
334
|
+
self.prompt.warn "History file needs a header with a `---` marker to support updating."
|
335
|
+
self.prompt.say "Adding an auto-generated one."
|
336
|
+
rest = header
|
337
|
+
header = self.load_and_render_template( 'History.erb', self.history_file )
|
338
|
+
end
|
339
|
+
|
340
|
+
header_char = self.header_char_for( self.history_file )
|
341
|
+
ext = self.history_file.extname
|
342
|
+
log_entries = if previous_tag
|
343
|
+
self.hg.log( rev: "#{previous_tag}~-2::" )
|
344
|
+
else
|
345
|
+
self.hg.log
|
346
|
+
end
|
347
|
+
|
348
|
+
Tempfile.create( ['History', ext], encoding: 'utf-8' ) do |tmp_copy|
|
349
|
+
tmp_copy.print( header )
|
350
|
+
tmp_copy.puts
|
351
|
+
|
352
|
+
tmp_copy.puts "%s %s [%s] %s" % [
|
353
|
+
header_char * 2,
|
354
|
+
version_tag,
|
355
|
+
Date.today.strftime( '%Y-%m-%d' ),
|
356
|
+
self.authors.first,
|
357
|
+
]
|
358
|
+
|
359
|
+
tmp_copy.puts
|
360
|
+
log_entries.each do |entry|
|
361
|
+
tmp_copy.puts "- %s" % [ entry.summary ]
|
362
|
+
end
|
363
|
+
tmp_copy.puts
|
364
|
+
tmp_copy.puts
|
365
|
+
|
366
|
+
tmp_copy.print( rest )
|
367
|
+
tmp_copy.close
|
368
|
+
|
369
|
+
TTY::Editor.open( tmp_copy.path )
|
370
|
+
|
371
|
+
if File.size?( tmp_copy.path )
|
372
|
+
cp( tmp_copy.path, self.history_file )
|
373
|
+
else
|
374
|
+
self.prompt.error "Empty file: aborting."
|
375
|
+
end
|
376
|
+
end
|
377
|
+
|
378
|
+
end
|
379
|
+
|
380
|
+
|
381
|
+
### Show debugging information.
|
382
|
+
def do_hg_debug( task, args )
|
383
|
+
self.prompt.say( "Hg Info", color: :bright_green )
|
384
|
+
|
385
|
+
self.prompt.say( "Mercurial version: " )
|
386
|
+
self.prompt.say( Hglib.version, color: :bold )
|
387
|
+
self.prompt.say( "Release tag prefix: " )
|
388
|
+
self.prompt.say( self.release_tag_prefix, color: :bold )
|
389
|
+
|
390
|
+
self.prompt.say( "Version tags:" )
|
391
|
+
self.get_version_tag_names.each do |tag|
|
392
|
+
self.prompt.say( '- ' )
|
393
|
+
self.prompt.say( tag, color: :bold )
|
394
|
+
end
|
395
|
+
|
396
|
+
self.prompt.say( "History file versions:" )
|
397
|
+
self.get_history_file_versions.each do |tag|
|
398
|
+
self.prompt.say( '- ' )
|
399
|
+
self.prompt.say( tag, color: :bold )
|
400
|
+
end
|
401
|
+
|
402
|
+
self.prompt.say( "Unhistoried version tags:" )
|
403
|
+
self.get_unhistoried_version_tags.each do |tag|
|
404
|
+
self.prompt.say( '- ' )
|
405
|
+
self.prompt.say( tag, color: :bold )
|
406
|
+
end
|
407
|
+
|
408
|
+
self.prompt.say( "\n" )
|
409
|
+
end
|
410
|
+
|
411
|
+
#
|
412
|
+
# utility methods
|
413
|
+
#
|
414
|
+
|
415
|
+
### Return an Hglib::Repo for the directory rake was invoked in, creating it if
|
416
|
+
### necessary.
|
417
|
+
def hg
|
418
|
+
@hg ||= Hglib.repo( Rake::DevEiate::PROJECT_DIR )
|
419
|
+
end
|
420
|
+
|
421
|
+
|
422
|
+
### Given a +status_hash+ like that returned by Hglib::Repo.status, return a
|
423
|
+
### string description of the files and their status.
|
424
|
+
def show_file_statuses( statuses )
|
425
|
+
lines = statuses.map do |entry|
|
426
|
+
status_color = STATUS_COLORS[ entry.status ]
|
427
|
+
" %s: %s" % [
|
428
|
+
self.pastel.white( entry.path.to_s ),
|
429
|
+
self.pastel.decorate( entry.status_description, *status_color ),
|
430
|
+
]
|
431
|
+
end
|
432
|
+
|
433
|
+
self.prompt.say( self.pastel.headline "Uncommitted files:" )
|
434
|
+
self.prompt.say( lines.join("\n") )
|
435
|
+
end
|
436
|
+
|
437
|
+
|
438
|
+
### Fetch the name of the current version's tag.
|
439
|
+
def current_version_tag
|
440
|
+
return [ self.release_tag_prefix, self.version ].join
|
441
|
+
end
|
442
|
+
|
443
|
+
|
444
|
+
### Fetch the name of the tag for the previous version.
|
445
|
+
def previous_version_tag
|
446
|
+
return self.get_version_tag_names.first
|
447
|
+
end
|
448
|
+
|
449
|
+
|
450
|
+
### Return a Regexp that matches the project's convention for versions.
|
451
|
+
def release_tag_pattern
|
452
|
+
prefix = self.release_tag_prefix
|
453
|
+
return /#{prefix}\d+(\.\d+)+/
|
454
|
+
end
|
455
|
+
|
456
|
+
|
457
|
+
### Fetch the list of names of tags that match the versioning scheme of this
|
458
|
+
### project.
|
459
|
+
def get_version_tag_names
|
460
|
+
tag_pattern = self.release_tag_pattern
|
461
|
+
return self.hg.tags.map( &:name ).grep( tag_pattern )
|
462
|
+
end
|
463
|
+
|
464
|
+
|
465
|
+
### Fetch the list of the versions of releases that have entries in the history
|
466
|
+
### file.
|
467
|
+
def get_history_file_versions
|
468
|
+
tag_pattern = self.release_tag_pattern
|
469
|
+
|
470
|
+
return IO.readlines( self.history_file ).grep( tag_pattern ).map do |line|
|
471
|
+
line[ /^(?:h\d\.|#+|=+)\s+(#{tag_pattern})\s+/, 1 ]
|
472
|
+
end.compact
|
473
|
+
end
|
474
|
+
|
475
|
+
|
476
|
+
### Read the list of tags and return any that don't have a corresponding section
|
477
|
+
### in the history file.
|
478
|
+
def get_unhistoried_version_tags( include_current_version: true )
|
479
|
+
release_tags = self.get_version_tag_names
|
480
|
+
release_tags.unshift( self.current_version_tag ) if include_current_version
|
481
|
+
|
482
|
+
self.get_history_file_versions.each do |tag|
|
483
|
+
release_tags.delete( tag )
|
484
|
+
end
|
485
|
+
|
486
|
+
return release_tags
|
487
|
+
end
|
488
|
+
|
489
|
+
|
490
|
+
### Generate a commit log and invoke the user's editor on it.
|
491
|
+
def edit_commit_log( logfile )
|
492
|
+
diff = self.hg.diff
|
493
|
+
|
494
|
+
File.open( logfile, 'w' ) do |fh|
|
495
|
+
fh.print( diff )
|
496
|
+
end
|
497
|
+
|
498
|
+
TTY::Editor.open( logfile )
|
499
|
+
end
|
500
|
+
|
501
|
+
|
502
|
+
### Add the list of +pathnames+ to the .hgignore list.
|
503
|
+
def hg_ignore_files( *pathnames )
|
504
|
+
patterns = pathnames.flatten.collect do |path|
|
505
|
+
'^' + Regexp.escape( path.to_s ) + '$'
|
506
|
+
end
|
507
|
+
self.trace "Ignoring %d files." % [ pathnames.length ]
|
508
|
+
|
509
|
+
IGNORE_FILE.open( File::CREAT|File::WRONLY|File::APPEND, 0644 ) do |fh|
|
510
|
+
fh.puts( patterns )
|
511
|
+
end
|
512
|
+
end
|
513
|
+
|
514
|
+
|
515
|
+
### Delete the files in the given +filelist+ after confirming with the user.
|
516
|
+
def delete_extra_files( *filelist )
|
517
|
+
description = humanize_file_list( filelist, ' ' )
|
518
|
+
self.prompt.say "Files to delete:"
|
519
|
+
self.prompt.say( description )
|
520
|
+
|
521
|
+
if self.prompt.yes?( "Really delete them?" ) {|q| q.default(false) }
|
522
|
+
filelist.each do |f|
|
523
|
+
rm_rf( f, verbose: true )
|
524
|
+
end
|
525
|
+
end
|
526
|
+
end
|
527
|
+
|
528
|
+
|
529
|
+
### Returns a human-scannable file list by joining and truncating the list if it's too long.
|
530
|
+
def humanize_file_list( list, indent=FILE_INDENT )
|
531
|
+
listtext = list[0..5].join( "\n#{indent}" )
|
532
|
+
if list.length > 5
|
533
|
+
listtext << " (and %d other/s)" % [ list.length - 5 ]
|
534
|
+
end
|
535
|
+
|
536
|
+
return listtext
|
537
|
+
end
|
538
|
+
|
539
|
+
|
540
|
+
end # module Rake::DevEiate::Hg
|
541
|
+
|
542
|
+
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# -*- ruby -*-
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require 'rubygems/package_task'
|
5
|
+
|
6
|
+
require 'rake/deveiate' unless defined?( Rake::DevEiate )
|
7
|
+
|
8
|
+
|
9
|
+
# Packaging tasks and functions
|
10
|
+
module Rake::DevEiate::Packaging
|
11
|
+
|
12
|
+
### Post-loading hook -- set up default attributes.
|
13
|
+
def setup( name, **options )
|
14
|
+
super if defined?( super )
|
15
|
+
|
16
|
+
gem_basename = "%s-%s" % [ name, self.version ]
|
17
|
+
|
18
|
+
@gem_filename = gem_basename + '.gem'
|
19
|
+
@gem_path = Rake::DevEiate::PKG_DIR + @gem_filename
|
20
|
+
end
|
21
|
+
|
22
|
+
##
|
23
|
+
# The filename of the generated gemfile
|
24
|
+
attr_reader :gem_filename
|
25
|
+
|
26
|
+
##
|
27
|
+
# The Pathname of the generated gemfile
|
28
|
+
attr_reader :gem_path
|
29
|
+
|
30
|
+
|
31
|
+
### Set up packaging tasks.
|
32
|
+
def define_tasks
|
33
|
+
super if defined?( super )
|
34
|
+
|
35
|
+
spec = self.gemspec
|
36
|
+
Gem::PackageTask.new( spec ).define
|
37
|
+
|
38
|
+
task :release_gem => :gem
|
39
|
+
end
|
40
|
+
|
41
|
+
end # module Rake::DevEiate::Packaging
|
42
|
+
|