mast 1.0.0 → 1.1

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.
data/MANIFEST CHANGED
@@ -1,23 +1,20 @@
1
- #!mast bin lib meta test [A-Z]*
2
- bin
1
+ HISTORY.rdoc
2
+ LICENSE
3
+ MANIFEST
4
+ README.rdoc
3
5
  bin/mast
4
- lib
5
6
  lib/mast
7
+ lib/mast.rb
6
8
  lib/mast/cli.rb
7
9
  lib/mast/core_ext.rb
8
10
  lib/mast/manifest.rb
9
- lib/mast.rb
10
- meta
11
11
  meta/authors
12
12
  meta/contact
13
13
  meta/description
14
+ meta/homepage
15
+ meta/namespace
14
16
  meta/package
15
- meta/project
17
+ meta/repository
16
18
  meta/ruby
17
19
  meta/sitemap
18
- meta/version
19
- test
20
- TUTORIAL.rdoc
21
- HISTORY.rdoc
22
- LICENSE
23
- README.rdoc
20
+ meta/version
@@ -1,7 +1,7 @@
1
1
  = Mast
2
2
 
3
- * http://proutils.rubyforge.org
4
- * http://protuils.rubyforge.org/mast
3
+ * home: http://proutils.github.com/mast
4
+ * source: http://github.com/proutils/mast
5
5
 
6
6
 
7
7
  == DESCRIPTION
@@ -11,7 +11,7 @@ It can be useful in conjunction with packaging tools (such as Box), or as a stan
11
11
  tool for monitoring file changes.
12
12
 
13
13
 
14
- == FEATURES/ISSUES
14
+ == FEATURES
15
15
 
16
16
  * Self-referential header makes updating manifests easy.
17
17
  * Checksum lists can highlight changes to current files.
@@ -24,11 +24,86 @@ Please see the HISTORY.rdoc file.
24
24
 
25
25
  == SYNOPSIS
26
26
 
27
- Usage is fairly straight forward.
27
+ Mast is a convenient commandline tool for generating manifest and file hash lists.
28
+ It makes the process very simple, and even allows manifests to be updated
29
+ without repeating inclusion/exclusion criteria by storing the command parameters
30
+ in a comment line at the top of the generated output.
28
31
 
29
- $ mast **/*
32
+ Lets try a simple example. Lets say we have the following folder structure:
30
33
 
31
- Please see the TUTORIAL file for further details.
34
+ $ ls -R
35
+ .:
36
+ demo_rtar mint
37
+
38
+ ./demo_rtar:
39
+ Lorem_ipsum.txt lib meta web
40
+
41
+ ./demo_rtar/lib:
42
+ demo_rock
43
+
44
+ ./demo_rtar/lib/demo_rock:
45
+ tryme.rb
46
+
47
+ ./demo_rtar/meta:
48
+ data
49
+
50
+ ./demo_rtar/web:
51
+ index.html rocklobster.jpg
52
+
53
+ ./mint:
54
+ loremipsum.txt tryme.rb
55
+
56
+ Now lets look at the same folder via 'mast'.
57
+
58
+ $ mast
59
+ #!mast
60
+ demo_rtar
61
+ demo_rtar/Lorem_ipsum.txt
62
+ demo_rtar/lib
63
+ demo_rtar/lib/demo_rock
64
+ demo_rtar/lib/demo_rock/tryme.rb
65
+ demo_rtar/meta
66
+ demo_rtar/meta/data
67
+ demo_rtar/web
68
+ demo_rtar/web/index.html
69
+ demo_rtar/web/rocklobster.jpg
70
+ mint
71
+ mint/loremipsum.txt
72
+ mint/tryme.rb
73
+
74
+ As you can see it has listed all the files contained in the current folder. Notice also the first
75
+ line is empty except for the '#' character. This is a standard shell comment mark. We can specify
76
+ special criteria to the mast command and these options will be reflected on this line. For example,
77
+ lets say the mint directory is extraneous and we do not want it included in the list of files.
78
+
79
+ $ mast -x mint
80
+ #!mast -x mint
81
+ demo_rtar
82
+ demo_rtar/Lorem_ipsum.txt
83
+ demo_rtar/lib
84
+ demo_rtar/lib/demo_rock
85
+ demo_rtar/lib/demo_rock/tryme.rb
86
+ demo_rtar/meta
87
+ demo_rtar/meta/data
88
+ demo_rtar/web
89
+ demo_rtar/web/index.html
90
+ demo_rtar/web/rocklobster.jpg
91
+
92
+ So you can see how the commandline options carry over to the top comment line of the ouput. The advantage of
93
+ this is that if you save the output to a standard location, ie. a file named MANIFEST or meta/manifest with
94
+ an optional .txt prefix (case insensitive), then you can automaitcally update the file by calling +mast update+.
95
+
96
+ $ mast -x mint > MANIFEST
97
+ $ mast update
98
+ MANIFEST updated.
99
+
100
+ You can also add a checksum to the file list.
101
+
102
+ $ mast -x mint -g sha1
103
+
104
+ Mast also provides options for ignoring files based on their basename, as well
105
+ as omitting default excludes and ignores so that all files are lists. Use the
106
+ --help option for more details.
32
107
 
33
108
 
34
109
  == HOW TO INSTALL
@@ -47,11 +122,11 @@ then download the tarball package and type:
47
122
  Windows users use 'ruby setup.rb all'.
48
123
 
49
124
 
50
- == LICENSE
125
+ == COPYRIGHT
51
126
 
52
127
  Copyright (c) 2009 Thomas Sawyer <transfire@gmail.com>
53
128
 
54
- This program is ditributed unser the terms of the GPL license.
129
+ This program is ditributed unser the terms of the MIT license.
55
130
 
56
- See COPYING file for details.
131
+ See LICENSE or COPYING file for details.
57
132
 
@@ -1 +1,5 @@
1
+ module Mast
2
+ VERSION = "1.1" #:till: VERSION="<%= version %>"
3
+ end
4
+
1
5
  require 'mast/manifest'
@@ -18,18 +18,20 @@
18
18
  # Commands:
19
19
  # -c --create Generate a new manifest. (default)
20
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.
21
+ # -l --list List the files given in the manifest file. (Use -f to specify an alternate file.)
23
22
  # -d --diff Diff manifest file against actual.
24
23
  # -n --new List existant files that are not given in the manifest.
25
24
  # -o --old List files given in the manifest but are non-existent.
26
25
  # --clean Remove non-manifest files. (Will ask for confirmation first.)
27
- # -v --verify (TODO) Verify that a manifest matches actual.
26
+ # -v --verify Verify that a manifest matches actual.
28
27
  # -h --help Display this help message.
29
28
  #
30
29
  # Options:
31
30
  # -a --all Include all files. This deactivates deafult exclusions
32
31
  # so it is possible to make complete list of all contents.
32
+ # --dir When creating a list include directory paths; by default
33
+ # only files are listed.
34
+ # -s --show Show files using the options from the manifest file.
33
35
  # -f --file PATH Path to manifest file. When using update command, if not
34
36
  # given then the file matching 'MANIFEST', case-insensitive
35
37
  # and with an optional '.txt' extension, will be looked for
@@ -40,7 +42,7 @@
40
42
  # -x --exclude PATH Exclude a file or dir from the manifest matching against
41
43
  # full pathname. You can use --exclude repeatedly.
42
44
  # --ignore PATH Exclude a file or dir from the manifest matching against
43
- # an extires basename. You can use --ignore repeatedly.
45
+ # an entries basename. You can use --ignore repeatedly.
44
46
  # -q --quiet Suppress extraneous output.
45
47
 
46
48
  require 'mast'
@@ -70,6 +72,8 @@ module Mast
70
72
  attr_accessor :include
71
73
  attr_accessor :exclude
72
74
  attr_accessor :all
75
+ attr_accessor :dir
76
+ attr_accessor :show
73
77
 
74
78
  #
75
79
  def initialize
@@ -83,8 +87,18 @@ module Mast
83
87
  @command = []
84
88
  end
85
89
 
86
- # Run command.
90
+ #
87
91
  def run
92
+ begin
93
+ run_command
94
+ rescue => err
95
+ raise err if $DEBUG
96
+ report err
97
+ end
98
+ end
99
+
100
+ # Run command.
101
+ def run_command
88
102
  optparse
89
103
  if @command.size > 1
90
104
  raise ArgumentError, "Please issue only one command."
@@ -94,7 +108,7 @@ module Mast
94
108
  when :create then generate
95
109
  when :update then update
96
110
  when :list then list
97
- when :show then show
111
+ #when :show then show
98
112
  when :diff then diff
99
113
  when :new then new
100
114
  when :old then old
@@ -113,15 +127,16 @@ module Mast
113
127
  [ '--digest' , '-g', GetoptLong::REQUIRED_ARGUMENT ],
114
128
  [ '--exclude', '-x', GetoptLong::REQUIRED_ARGUMENT ],
115
129
  #[ '--include', '-i', GetoptLong::REQUIRED_ARGUMENT ],
116
- [ '--ignore', GetoptLong::REQUIRED_ARGUMENT ],
130
+ [ '--ignore' , '-i', GetoptLong::REQUIRED_ARGUMENT ],
117
131
  [ '--all' , '-a', GetoptLong::NO_ARGUMENT ],
132
+ [ '--dir' , GetoptLong::NO_ARGUMENT ],
133
+ [ '--show' , '-s', GetoptLong::NO_ARGUMENT ],
118
134
  [ '--quiet' , '-q', GetoptLong::NO_ARGUMENT ],
119
135
  # commands
120
136
  [ '--help' , '-h', GetoptLong::NO_ARGUMENT ],
121
137
  [ '--create' , '-c', GetoptLong::NO_ARGUMENT ],
122
138
  [ '--update' , '-u', GetoptLong::NO_ARGUMENT ],
123
139
  [ '--list' , '-l', GetoptLong::NO_ARGUMENT ],
124
- [ '--show' , '-s', GetoptLong::NO_ARGUMENT ],
125
140
  [ '--diff' , '-d', GetoptLong::NO_ARGUMENT ],
126
141
  [ '--new' , '-n', GetoptLong::NO_ARGUMENT ],
127
142
  [ '--old' , '-o', GetoptLong::NO_ARGUMENT ],
@@ -139,8 +154,8 @@ module Mast
139
154
  @command << :update
140
155
  when '--list'
141
156
  @command << :list
142
- when '--show'
143
- @command << :show
157
+ #when '--show'
158
+ # @command << :show
144
159
  when '--diff'
145
160
  @command << :diff
146
161
  when '--new'
@@ -162,6 +177,10 @@ module Mast
162
177
  # @include << val
163
178
  #when '--ignore'
164
179
  # @ignore << val
180
+ when '--show'
181
+ @show = true
182
+ when '--dir'
183
+ @dir = true
165
184
  when '--all'
166
185
  @all = true
167
186
  when '--quiet'
@@ -213,10 +232,10 @@ module Mast
213
232
  puts manifest.filelist
214
233
  end
215
234
 
216
- # List files in manifest file.
217
- def show
218
- puts manifest.showlist
219
- end
235
+ #
236
+ #def show
237
+ # puts manifest.showlist
238
+ #end
220
239
 
221
240
  # Show diff comparison between listed and actual.
222
241
  def diff
@@ -282,7 +301,7 @@ module Mast
282
301
 
283
302
  # Options for Manifest class taken from commandline arguments.
284
303
  def manifest_options
285
- { :file=>file, :digest=>digest, :exclude=>exclude, :ignore=>ignore, :all=>all, :include=>include }
304
+ { :file=>file, :digest=>digest, :exclude=>exclude, :ignore=>ignore, :all=>all, :dir=>dir, :include=>include, :show=>show }
286
305
  end
287
306
 
288
307
  # Quiet opertation?
@@ -302,19 +321,24 @@ module Mast
302
321
  ask("The above files will be removed. Continue?", "yN")
303
322
  end
304
323
 
324
+ #
325
+ def report(message)
326
+ $stderr << "#{message}\n" unless quiet?
327
+ end
328
+
305
329
  # Report manifest created.
306
330
  def report_created(file)
307
331
  file = File.basename(file)
308
- puts "#{file} created." unless quiet?
332
+ report "#{file} created."
309
333
  end
310
334
 
311
335
  # Report manifest updated.
312
336
  def report_updated(file)
313
337
  if file
314
338
  file = File.basename(file)
315
- puts "#{file} updated." unless quiet?
339
+ report "#{file} updated."
316
340
  else
317
- puts "Manifest file doesn't exit."
341
+ report "Manifest file doesn't exit."
318
342
  end
319
343
  end
320
344
 
@@ -341,7 +365,7 @@ module Mast
341
365
  puts list.join("\n")
342
366
  end
343
367
 
344
- # Report missing manifest file.
368
+ #
345
369
  def report_whatsold(list)
346
370
  puts list.join("\n")
347
371
  end
@@ -361,30 +385,30 @@ module Mast
361
385
 
362
386
  # Report missing manifest file.
363
387
  def report_manifest_missing
364
- puts "No manifest file."
388
+ report "No manifest file."
365
389
  end
366
390
 
367
391
  # Report action cancelled.
368
392
  def report_cancelled(action)
369
- puts "#{action} cancelled."
393
+ report "#{action} cancelled."
370
394
  end
371
395
 
372
396
  # Report manifest overwrite.
373
397
  def report_overwrite(manifest)
374
- puts "#{manifest.filename} already exists."
398
+ report "#{manifest.filename} already exists."
375
399
  end
376
400
 
377
401
  # Warn that a manifest already exist higher in this hierarchy.
378
402
  def report_warn_shadowing(manifest)
379
- puts "Shadowing #{manifest.file}."
403
+ report "Shadowing #{manifest.file}."
380
404
  end
381
405
 
382
406
  #
383
407
  def report_verify(check)
384
408
  if check
385
- puts "Manifest if good."
409
+ report "Manifest if good."
386
410
  else
387
- puts "Manifest if bad!"
411
+ report "Manifest if bad!"
388
412
  end
389
413
  end
390
414
  end
@@ -17,7 +17,7 @@ module Mast
17
17
  # TODO: Consider adding @include options rather then scanning entire directory.
18
18
  # But this can't be done unless we can write a routine that can look at @include
19
19
  # and reduce it to non-overlapping matches. Eg. [doc, doc/rdoc] should reduce
20
- # to just [doc]. Otherwise we will get duplicate entries, b/c the #output
20
+ # to just [doc]. Otherwise we will get duplicate entries, b/c the #output
21
21
  # method is written for speed and low memory footprint. This might mean @include
22
22
  # can't use file globs.
23
23
  #
@@ -50,7 +50,7 @@ module Mast
50
50
  def self.open(file=nil, options={})
51
51
  unless file
52
52
  file = Dir.glob(filename, File::FNM_CASEFOLD).first
53
- raise LoadError, "Manifest file is required." unless file
53
+ raise NoManifestError, "Manifest file is required." unless file
54
54
  end
55
55
  options[:file] = file
56
56
  new(options)
@@ -68,6 +68,13 @@ module Mast
68
68
  # Do not exclude standard exclusions.
69
69
  attr_accessor :all
70
70
 
71
+ # Include directories.
72
+ attr_accessor :dir
73
+
74
+ # Show as if another manifest (eg. use files options).
75
+ # TODO: Change name?
76
+ attr_accessor :show
77
+
71
78
  # What files to include. Defaults to ['*'].
72
79
  # Note that Mast automatically recurses through
73
80
  # directory entries, so using '**/*' would simply
@@ -89,6 +96,12 @@ module Mast
89
96
  #
90
97
  alias_method :all?, :all
91
98
 
99
+ #
100
+ alias_method :dir?, :dir
101
+
102
+ #
103
+ alias_method :show?, :show
104
+
92
105
  # New Manifest object.
93
106
  #
94
107
  def initialize(options={})
@@ -97,6 +110,8 @@ module Mast
97
110
  @ignore = []
98
111
  @format = 'csf'
99
112
  @all = false
113
+ @dir = false
114
+ @show = false
100
115
  @digest = nil
101
116
  @directory = Dir.pwd
102
117
 
@@ -132,7 +147,7 @@ module Mast
132
147
 
133
148
  #
134
149
  def file
135
- @file ||= Dir[File.join(directory, DEFAULT_FILE)].first || 'MANIFEST'
150
+ @file ||= Dir.glob(File.join(directory, DEFAULT_FILE), File::FNM_CASEFOLD).first || 'MANIFEST'
136
151
  end
137
152
 
138
153
  #
@@ -151,6 +166,7 @@ module Mast
151
166
 
152
167
  # Generate manifest.
153
168
  def generate(out=$stdout)
169
+ parse_topline unless read? if show?
154
170
  out << topline_string
155
171
  output(out)
156
172
  end
@@ -210,8 +226,12 @@ module Mast
210
226
  # Clean non-manifest files.
211
227
  def clean
212
228
  cfiles, cdirs = cleanlist.partition{ |f| !File.directory?(f) }
213
- FileUtils.rm(cfiles)
214
- FileUtils.rmdir(cdirs)
229
+ if cfiles.empty? && cdirs.empty?
230
+ $stderr < "No difference between list and actual.\n"
231
+ else
232
+ FileUtils.rm(cfiles)
233
+ FileUtils.rmdir(cdirs)
234
+ end
215
235
  end
216
236
 
217
237
  # List of current files.
@@ -236,13 +256,16 @@ module Mast
236
256
 
237
257
  #
238
258
  def cleanlist
259
+ showlist - filelist
260
+ end
261
+
262
+ # Files not listed in manifest.
263
+ def unlisted
239
264
  list = []
240
265
  Dir.chdir(directory) do
241
- keep = Dir.glob('*').select{|f| File.directory?(f)} # keep top-level directories?
242
- keep << filename # keep manifest file
243
- list = Dir.glob('**/*') - (filelist + keep)
266
+ list = Dir.glob('**/*')
244
267
  end
245
- list
268
+ list - filelist
246
269
  end
247
270
 
248
271
  #
@@ -293,11 +316,14 @@ module Mast
293
316
  files = files.reject{ |f| ignores.any?{ |i| File.fnmatch(i, File.basename(f)) } }
294
317
  files = files.sort
295
318
  files.each do |file|
296
- sum = checksum(file,digest)
297
- sum = sum + ' ' if sum
298
- out << "#{sum}#{file}"
299
- out << "\n" unless Array === out
300
- if File.directory?(file)
319
+ is_dir = File.directory?(file)
320
+ if !is_dir || (is_dir && dir?)
321
+ sum = checksum(file,digest)
322
+ sum = sum + ' ' if sum
323
+ out << "#{sum}#{file}"
324
+ out << "\n" unless Array === out
325
+ end
326
+ if is_dir
301
327
  rec_output(File.join(file,'*'), out)
302
328
  end
303
329
  end