mast 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/MANIFEST ADDED
@@ -0,0 +1,23 @@
1
+ #!mast bin lib meta test [A-Z]*
2
+ bin
3
+ bin/mast
4
+ lib
5
+ lib/mast
6
+ lib/mast/cli.rb
7
+ lib/mast/core_ext.rb
8
+ lib/mast/manifest.rb
9
+ lib/mast.rb
10
+ meta
11
+ meta/authors
12
+ meta/contact
13
+ meta/description
14
+ meta/package
15
+ meta/project
16
+ meta/ruby
17
+ meta/sitemap
18
+ meta/version
19
+ test
20
+ TUTORIAL.rdoc
21
+ HISTORY.rdoc
22
+ LICENSE
23
+ README.rdoc
data/README.rdoc ADDED
@@ -0,0 +1,57 @@
1
+ = Mast
2
+
3
+ * http://proutils.rubyforge.org
4
+ * http://protuils.rubyforge.org/mast
5
+
6
+
7
+ == DESCRIPTION
8
+
9
+ Mast is a commandline utility for generating MANIFEST lists and optionally checksums.
10
+ It can be useful in conjunction with packaging tools (such as Box), or as a stand-alone
11
+ tool for monitoring file changes.
12
+
13
+
14
+ == FEATURES/ISSUES
15
+
16
+ * Self-referential header makes updating manifests easy.
17
+ * Checksum lists can highlight changes to current files.
18
+
19
+
20
+ == RELEASE NOTES
21
+
22
+ Please see the HISTORY.rdoc file.
23
+
24
+
25
+ == SYNOPSIS
26
+
27
+ Usage is fairly straight forward.
28
+
29
+ $ mast **/*
30
+
31
+ Please see the TUTORIAL file for further details.
32
+
33
+
34
+ == HOW TO INSTALL
35
+
36
+ To install with RubyGems simply open a console and type:
37
+
38
+ gem install mast
39
+
40
+ Local installation requires Setup.rb (gem install setup),
41
+ then download the tarball package and type:
42
+
43
+ tar -xvzf mast-1.0.0.tgz
44
+ cd mast-1.0.0.tgz
45
+ sudo setup.rb all
46
+
47
+ Windows users use 'ruby setup.rb all'.
48
+
49
+
50
+ == LICENSE
51
+
52
+ Copyright (c) 2009 Thomas Sawyer <transfire@gmail.com>
53
+
54
+ This program is ditributed unser the terms of the GPL license.
55
+
56
+ See COPYING file for details.
57
+
data/TUTORIAL.rdoc ADDED
@@ -0,0 +1,83 @@
1
+ = Mast Tutorial
2
+
3
+ Mast is a convenient commandline tool for generating manifest and file hash lists.
4
+ It makes the process very simple, and even allows manifests to be updated
5
+ without repeating inclusion/exclusion criteria by storing the command parameters
6
+ in a comment line at the top of the generated output.
7
+
8
+ Lets try a simple example. Lets say we have the following folder structure:
9
+
10
+ $ ls -R
11
+ .:
12
+ demo_rtar mint
13
+
14
+ ./demo_rtar:
15
+ Lorem_ipsum.txt lib meta web
16
+
17
+ ./demo_rtar/lib:
18
+ demo_rock
19
+
20
+ ./demo_rtar/lib/demo_rock:
21
+ tryme.rb
22
+
23
+ ./demo_rtar/meta:
24
+ data
25
+
26
+ ./demo_rtar/web:
27
+ index.html rocklobster.jpg
28
+
29
+ ./mint:
30
+ loremipsum.txt tryme.rb
31
+
32
+ Now lets look at the same folder via 'mast'.
33
+
34
+ $ mast
35
+ #!mast
36
+ demo_rtar
37
+ demo_rtar/Lorem_ipsum.txt
38
+ demo_rtar/lib
39
+ demo_rtar/lib/demo_rock
40
+ demo_rtar/lib/demo_rock/tryme.rb
41
+ demo_rtar/meta
42
+ demo_rtar/meta/data
43
+ demo_rtar/web
44
+ demo_rtar/web/index.html
45
+ demo_rtar/web/rocklobster.jpg
46
+ mint
47
+ mint/loremipsum.txt
48
+ mint/tryme.rb
49
+
50
+ As you can see it has listed all the files contained in the current folder. Notice also the first
51
+ line is empty except for the '#' character. This is a standard shell comment mark. We can specify
52
+ special criteria to the mast command and these options will be reflected on this line. For example,
53
+ lets say the mint directory is extraneous and we do not want it included in the list of files.
54
+
55
+ $ mast -x mint
56
+ #!mast -x mint
57
+ demo_rtar
58
+ demo_rtar/Lorem_ipsum.txt
59
+ demo_rtar/lib
60
+ demo_rtar/lib/demo_rock
61
+ demo_rtar/lib/demo_rock/tryme.rb
62
+ demo_rtar/meta
63
+ demo_rtar/meta/data
64
+ demo_rtar/web
65
+ demo_rtar/web/index.html
66
+ demo_rtar/web/rocklobster.jpg
67
+
68
+ So you can see how the commandline options carry over to the top comment line of the ouput. The advantage of
69
+ this is that if you save the output to a standard location, ie. a file named MANIFEST or meta/manifest with
70
+ an optional .txt prefix (case insensitive), then you can automaitcally update the file by calling +mast update+.
71
+
72
+ $ mast -x mint > MANIFEST
73
+ $ mast update
74
+ MANIFEST updated.
75
+
76
+ You can also add a checksum to the file list.
77
+
78
+ $ mast -x mint -g sha1
79
+
80
+ Mast also provides options for ignoring files based on their basename, as well
81
+ as omitting default excludes and ignores so that all files are lists. Use the
82
+ --help option for more details.
83
+
data/bin/mast ADDED
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env ruby
2
+ require 'mast/cli'
3
+ Mast::Cli.run
4
+
data/lib/mast.rb ADDED
@@ -0,0 +1 @@
1
+ require 'mast/manifest'
data/lib/mast/cli.rb ADDED
@@ -0,0 +1,480 @@
1
+ # mast v1.0.0
2
+ #
3
+ # Usage:
4
+ # mast [command] [options...]
5
+ #
6
+ # The manifest listing tool is used to list, create or update a
7
+ # manifest for a directory (eg. to define a "package"), or compare
8
+ # a manifest to actual directory contents. Mast is part of the
9
+ # ProUtils set of tools.
10
+ #
11
+ # When no command is given, a manifest is dumped to standard out.
12
+ # If --file is specified, it will generate to that file instead.
13
+ #
14
+ # Examples:
15
+ # mast
16
+ # mast -u -f PUBLISH
17
+ #
18
+ # Commands:
19
+ # -c --create Generate a new manifest. (default)
20
+ # -u --update Update an existing manifest.
21
+ # -l --list List the files give in the manifest file. (Use -f to specify an alternate file.)
22
+ # -s --show Show all files that would appear in the manifest file if it were updated.
23
+ # -d --diff Diff manifest file against actual.
24
+ # -n --new List existant files that are not given in the manifest.
25
+ # -o --old List files given in the manifest but are non-existent.
26
+ # --clean Remove non-manifest files. (Will ask for confirmation first.)
27
+ # -v --verify (TODO) Verify that a manifest matches actual.
28
+ # -h --help Display this help message.
29
+ #
30
+ # Options:
31
+ # -a --all Include all files. This deactivates deafult exclusions
32
+ # so it is possible to make complete list of all contents.
33
+ # -f --file PATH Path to manifest file. When using update command, if not
34
+ # given then the file matching 'MANIFEST', case-insensitive
35
+ # and with an optional '.txt' extension, will be looked for
36
+ # in the current directory. If the path of the manifest file
37
+ # is anything else then --file option must be specified.
38
+ # -g --digest TYPE Include crytogrpahic signiture. Type can be either
39
+ # md5, sha1, sha128, sha256, or sha512.
40
+ # -x --exclude PATH Exclude a file or dir from the manifest matching against
41
+ # full pathname. You can use --exclude repeatedly.
42
+ # --ignore PATH Exclude a file or dir from the manifest matching against
43
+ # an extires basename. You can use --ignore repeatedly.
44
+ # -q --quiet Suppress extraneous output.
45
+
46
+ require 'mast'
47
+
48
+ # both of these can be replaced by using Clio instead.
49
+ require 'getoptlong'
50
+ require 'facets/kernel/ask'
51
+
52
+ module Mast
53
+
54
+ ARGVO = ARGV.dup
55
+
56
+ # Manifest Console Command
57
+ #
58
+ class Cli
59
+
60
+ def self.run
61
+ new.run
62
+ end
63
+
64
+ DIGESTS = [:md5, :sha1, :sha128, :sha256, :sha512]
65
+
66
+ attr_accessor :quiet
67
+ attr_accessor :file
68
+ attr_accessor :digest
69
+ attr_accessor :ignore
70
+ attr_accessor :include
71
+ attr_accessor :exclude
72
+ attr_accessor :all
73
+
74
+ #
75
+ def initialize
76
+ @quiet = false
77
+ @all = false
78
+ @file = nil
79
+ @digest = nil
80
+ @exclude = []
81
+ @include = []
82
+ @ignore = []
83
+ @command = []
84
+ end
85
+
86
+ # Run command.
87
+ def run
88
+ optparse
89
+ if @command.size > 1
90
+ raise ArgumentError, "Please issue only one command."
91
+ end
92
+ case @command.first
93
+ when :help then help
94
+ when :create then generate
95
+ when :update then update
96
+ when :list then list
97
+ when :show then show
98
+ when :diff then diff
99
+ when :new then new
100
+ when :old then old
101
+ when :verify then verify
102
+ when :clean then clean
103
+ else
104
+ generate
105
+ end
106
+ end
107
+
108
+ # Parse command line options.
109
+ def optparse
110
+ opts = GetoptLong.new(
111
+ # options
112
+ [ '--file' , '-f', GetoptLong::REQUIRED_ARGUMENT ],
113
+ [ '--digest' , '-g', GetoptLong::REQUIRED_ARGUMENT ],
114
+ [ '--exclude', '-x', GetoptLong::REQUIRED_ARGUMENT ],
115
+ #[ '--include', '-i', GetoptLong::REQUIRED_ARGUMENT ],
116
+ [ '--ignore', GetoptLong::REQUIRED_ARGUMENT ],
117
+ [ '--all' , '-a', GetoptLong::NO_ARGUMENT ],
118
+ [ '--quiet' , '-q', GetoptLong::NO_ARGUMENT ],
119
+ # commands
120
+ [ '--help' , '-h', GetoptLong::NO_ARGUMENT ],
121
+ [ '--create' , '-c', GetoptLong::NO_ARGUMENT ],
122
+ [ '--update' , '-u', GetoptLong::NO_ARGUMENT ],
123
+ [ '--list' , '-l', GetoptLong::NO_ARGUMENT ],
124
+ [ '--show' , '-s', GetoptLong::NO_ARGUMENT ],
125
+ [ '--diff' , '-d', GetoptLong::NO_ARGUMENT ],
126
+ [ '--new' , '-n', GetoptLong::NO_ARGUMENT ],
127
+ [ '--old' , '-o', GetoptLong::NO_ARGUMENT ],
128
+ [ '--verify' , '-v', GetoptLong::NO_ARGUMENT ],
129
+ [ '--clean' , GetoptLong::NO_ARGUMENT ]
130
+ )
131
+
132
+ opts.each do |key, val|
133
+ case key
134
+ when '--help'
135
+ @command << :help
136
+ when '--create'
137
+ @command << :create
138
+ when '--update'
139
+ @command << :update
140
+ when '--list'
141
+ @command << :list
142
+ when '--show'
143
+ @command << :show
144
+ when '--diff'
145
+ @command << :diff
146
+ when '--new'
147
+ @command << :new
148
+ when '--old'
149
+ @command << :old
150
+ when '--verify'
151
+ @command << :verify
152
+ when '--clean'
153
+ @command << :clean
154
+
155
+ when '--file'
156
+ @file = val
157
+ when '--digest'
158
+ @digest = val
159
+ when '--exclude'
160
+ @exclude << val
161
+ #when '--include'
162
+ # @include << val
163
+ #when '--ignore'
164
+ # @ignore << val
165
+ when '--all'
166
+ @all = true
167
+ when '--quiet'
168
+ @quiet = true
169
+ end
170
+ end
171
+
172
+ #unless args.empty?
173
+ # if File.file?(args[0])
174
+ # opts[:file] = args[0]
175
+ # opts[:directory] = args[1] if args[1]
176
+ # else
177
+ # opts[:directory] = args[0]
178
+ # opts[:file] = args[1] if args[1]
179
+ # end
180
+ #end
181
+
182
+ @include = ARGV.empty? ? nil : ARGV.dup
183
+ end
184
+
185
+ #def default; generate; end
186
+
187
+ # Default command -- output manifest.
188
+ #
189
+ def generate
190
+ #if file
191
+ # update
192
+ #else
193
+ manifest.generate
194
+ #end
195
+ end
196
+
197
+ # Update a MANIFEST file for this package.
198
+ #
199
+ def update
200
+ begin
201
+ file = manifest.update
202
+ rescue NoManifestError => e
203
+ puts e.message
204
+ exit -1
205
+ end
206
+ report_updated(file)
207
+ end
208
+
209
+ alias_method :up, :update
210
+
211
+ # List files in manifest file.
212
+ def list
213
+ puts manifest.filelist
214
+ end
215
+
216
+ # List files in manifest file.
217
+ def show
218
+ puts manifest.showlist
219
+ end
220
+
221
+ # Show diff comparison between listed and actual.
222
+ def diff
223
+ result = manifest.diff
224
+ report_difference(result)
225
+ end
226
+
227
+ # Files listed in manifest, but not found.
228
+ def old
229
+ list = manifest.whatsold
230
+ unless list.empty?
231
+ report_whatsold(list)
232
+ end
233
+ end
234
+
235
+ # Files found, but not listed in manifest.
236
+ def new
237
+ list = manifest.whatsnew
238
+ unless list.empty?
239
+ report_whatsnew(list)
240
+ end
241
+ end
242
+
243
+ #
244
+ def verify
245
+ check = manifest.verify
246
+ report_verify(check)
247
+ exit -1 unless check
248
+ end
249
+
250
+ # Clean (or clobber if you prefer) non-manifest files.
251
+ def clean
252
+ answer = confirm_clean(manifest.cleanlist)
253
+ case answer.downcase
254
+ when 'y', 'yes'
255
+ manifest.clean
256
+ else
257
+ report_cancelled('Clean')
258
+ exit!
259
+ end
260
+ end
261
+
262
+ # Display command help information.
263
+ def help
264
+ report_help
265
+ end
266
+
267
+ private
268
+
269
+ #
270
+ def manifest
271
+ @manifest ||= Manifest.new(manifest_options)
272
+ #@manifest ||= (
273
+ # begin
274
+ # manifest = Manifest.open(file, manifest_options)
275
+ # manifest
276
+ # rescue LoadError
277
+ # report_manifest_missing
278
+ # exit 0
279
+ # end
280
+ #)
281
+ end
282
+
283
+ # Options for Manifest class taken from commandline arguments.
284
+ def manifest_options
285
+ { :file=>file, :digest=>digest, :exclude=>exclude, :ignore=>ignore, :all=>all, :include=>include }
286
+ end
287
+
288
+ # Quiet opertation?
289
+ def quiet?
290
+ @quiet
291
+ end
292
+
293
+ # Get confirmation for clean.
294
+ def confirm_clean(list)
295
+ puts list.join("\n")
296
+ ask("The above files will be removed. Continue?", "yN")
297
+ end
298
+
299
+ # Get confirmation for clobber.
300
+ def confirm_clobber(list)
301
+ puts list.join("\n")
302
+ ask("The above files will be removed. Continue?", "yN")
303
+ end
304
+
305
+ # Report manifest created.
306
+ def report_created(file)
307
+ file = File.basename(file)
308
+ puts "#{file} created." unless quiet?
309
+ end
310
+
311
+ # Report manifest updated.
312
+ def report_updated(file)
313
+ if file
314
+ file = File.basename(file)
315
+ puts "#{file} updated." unless quiet?
316
+ else
317
+ puts "Manifest file doesn't exit."
318
+ end
319
+ end
320
+
321
+ # Display diff between file and actual.
322
+ #--
323
+ # TODO What about checkmode?
324
+ #++
325
+ def report_difference(result)
326
+ output = nil
327
+ if pass = result.empty?
328
+ if @checkmode
329
+ output = justified('Manifest', '[PASS]') + "\n"
330
+ else
331
+ #"Manifest is current."
332
+ end
333
+ else
334
+ output = result
335
+ end
336
+ puts output if output
337
+ end
338
+
339
+ # Report missing manifest file.
340
+ def report_whatsnew(list)
341
+ puts list.join("\n")
342
+ end
343
+
344
+ # Report missing manifest file.
345
+ def report_whatsold(list)
346
+ puts list.join("\n")
347
+ end
348
+
349
+ # Show help.
350
+ def report_help
351
+ doc = false
352
+ File.readlines(__FILE__).each do |line|
353
+ line = line.strip
354
+ break if doc && line.empty?
355
+ next if line =~ /^#!/
356
+ next if line.empty?
357
+ puts line[1..-1].sub(/^\ \ /,'')
358
+ doc = true
359
+ end
360
+ end
361
+
362
+ # Report missing manifest file.
363
+ def report_manifest_missing
364
+ puts "No manifest file."
365
+ end
366
+
367
+ # Report action cancelled.
368
+ def report_cancelled(action)
369
+ puts "#{action} cancelled."
370
+ end
371
+
372
+ # Report manifest overwrite.
373
+ def report_overwrite(manifest)
374
+ puts "#{manifest.filename} already exists."
375
+ end
376
+
377
+ # Warn that a manifest already exist higher in this hierarchy.
378
+ def report_warn_shadowing(manifest)
379
+ puts "Shadowing #{manifest.file}."
380
+ end
381
+
382
+ #
383
+ def report_verify(check)
384
+ if check
385
+ puts "Manifest if good."
386
+ else
387
+ puts "Manifest if bad!"
388
+ end
389
+ end
390
+ end
391
+
392
+ end
393
+
394
+ =begin scrap
395
+
396
+ # # Lookup manifest.
397
+ #
398
+ # def manifest(create_missing=false)
399
+ # @manifest ||= (
400
+ # file = @options[:file]
401
+ # #manifest = file ? Manifest.open(file) : Manifest.lookup
402
+ # manifest = nil
403
+ #
404
+ # if file
405
+ # manifest = Manifest.open(file, @options)
406
+ # elsif create_missing
407
+ # manifest = Manifest.new(@options)
408
+ # else
409
+ # manifest = nil
410
+ # end
411
+ #
412
+ # if manifest
413
+ # #manifest.send(:set, @options)
414
+ # else
415
+ # report_manifest_missing
416
+ # exit 0
417
+ # end
418
+ # manifest
419
+ # )
420
+ # end
421
+
422
+ # @manifest ||= (
423
+ # file = @options[:file]
424
+ # #manifest = file ? Manifest.open(file) : Manifest.lookup
425
+ # manifest = nil
426
+ #
427
+ # if file
428
+ # manifest = Manifest.open(file)
429
+ # elsif create_missing
430
+ # manifest = Manifest.new
431
+ # else
432
+ # manifest = nil
433
+ # end
434
+ #
435
+ # if manifest
436
+ # manifest.change_options(@options)
437
+ # else
438
+ # report_manifest_missing
439
+ # exit 0
440
+ # end
441
+ # manifest
442
+ # )
443
+ # end
444
+
445
+ # # Generate manifest. By default it is a very simple filename
446
+ # # list. The digest can be supplied and a checksum will
447
+ # # be given before each filename.
448
+ #
449
+ # def create
450
+ # manifest = Manifest.new #lookup
451
+ #
452
+ # return report_overwrite(manifest) if (
453
+ # manifest and manifest.location == Dir.pwd
454
+ # )
455
+ #
456
+ # report_warn_shadowing(manifest) if manifest
457
+ #
458
+ # manifest = Manifest.new(options)
459
+ # file = manifest.create
460
+ # report_created(file)
461
+ # end
462
+
463
+ # # Clobber non-manifest files.
464
+ # #--
465
+ # # TODO Should clobber work off the manifest file itself
466
+ # #++
467
+ #
468
+ # def clobber
469
+ # ansr = confirm_clobber(manifest.toss)
470
+ # case ansr.downcase
471
+ # when 'y', 'yes'
472
+ # manifest.clobber
473
+ # else
474
+ # report_cancelled('Clobber')
475
+ # exit!
476
+ # end
477
+ # end
478
+
479
+ =end
480
+