di 0.2.3 → 0.3.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 (4) hide show
  1. data/HISTORY +14 -0
  2. data/di.gemspec +3 -3
  3. data/lib/di.rb +67 -69
  4. metadata +5 -5
data/HISTORY CHANGED
@@ -1,3 +1,17 @@
1
+ == 0.3.0 2012-05-14
2
+
3
+ * Fix pagerizing with Ruby 1.9+ and turn it on by default.
4
+
5
+ * Complement a missing implementation of --unidirectional-new-file.
6
+
7
+ * Complement a missing implementation of -S/--starting-file=FILE.
8
+
9
+ * Add support for --suppress-blank-empty.
10
+
11
+ * Fix handling of -T/--initial-tab.
12
+
13
+ * Remove -L which use has long been deprecated.
14
+
1
15
  == 0.2.3 2012-03-29
2
16
 
3
17
  * Fix the case where comparing two directories fails when the latter
data/di.gemspec CHANGED
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = "di"
8
- s.version = "0.2.3"
8
+ s.version = "0.3.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Akinori MUSHA"]
12
- s.date = "2012-03-29"
12
+ s.date = "2012-05-14"
13
13
  s.description = "The di(1) command wraps around GNU diff(1) to provide reasonable\ndefault settings and some original features.\n"
14
14
  s.email = "knu@idaemons.org"
15
15
  s.executables = ["di"]
@@ -32,7 +32,7 @@ Gem::Specification.new do |s|
32
32
  s.homepage = "https://github.com/knu/di"
33
33
  s.require_paths = ["lib"]
34
34
  s.required_ruby_version = Gem::Requirement.new(">= 1.8.7")
35
- s.rubygems_version = "1.8.15"
35
+ s.rubygems_version = "1.8.23"
36
36
  s.summary = "A wrapper around GNU diff(1)"
37
37
 
38
38
  if s.respond_to? :specification_version then
data/lib/di.rb CHANGED
@@ -28,13 +28,12 @@
28
28
  # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29
29
  # SUCH DAMAGE.
30
30
 
31
- MYVERSION = "0.2.3"
31
+ MYVERSION = "0.3.0"
32
32
  MYNAME = File.basename($0)
33
33
  MYCOPYRIGHT = "Copyright (c) 2008, 2009, 2010, 2011, 2012 Akinori MUSHA"
34
34
 
35
35
  DIFF_CMD = ENV.fetch('DIFF', 'diff')
36
36
  ENV_NAME = "#{MYNAME.tr('-a-z', '_A-Z')}_OPTIONS"
37
- EMPTYFILE = '/dev/null'
38
37
 
39
38
  RSYNC_EXCLUDE_FILE_GLOBS = [
40
39
  'tags', 'TAGS', 'GTAGS', 'GRTAGS', 'GSYMS', 'GPATH',
@@ -58,6 +57,8 @@ FIGNORE_GLOBS = ENV.fetch('FIGNORE', '').split(':').map { |pat|
58
57
  '*' + pat
59
58
  }
60
59
 
60
+ IO::NULL = '/dev/null' unless defined? IO::NULL
61
+
61
62
  def main(args)
62
63
  setup
63
64
 
@@ -116,31 +117,31 @@ usage: #{MYNAME} [flags] [files]
116
117
  }
117
118
 
118
119
  opts.on('--[no-]pager',
119
- 'Pipe output into pager if stdout is a terminal. [!][*]') { |val|
120
- $diff.use_pager = val if $stdout.tty? && RUBY_VERSION < "1.9"
120
+ 'Pipe output into pager if stdout is a terminal. [+][*]') { |val|
121
+ $diff.use_pager = val if $stdout.tty?
121
122
  }
122
123
  opts.on('--[no-]color',
123
- 'Colorize output if stdout is a terminal and the format is unified or context. [!][*]') { |val|
124
+ 'Colorize output if stdout is a terminal and the format is unified or context. [+][*]') { |val|
124
125
  $diff.colorize = val if $stdout.tty?
125
126
  }
126
127
  opts.on('--[no-]highlight-whitespace',
127
- 'Highlight suspicious whitespace differences in colorized output. [!][*]') { |val|
128
+ 'Highlight suspicious whitespace differences in colorized output. [+][*]') { |val|
128
129
  $diff.highlight_whitespace = val
129
130
  }
130
131
  opts.on('--[no-]rsync-exclude', '--[no-]cvs-exclude',
131
- 'Exclude some kinds of files and directories a la rsync(1). [!][*]') { |val|
132
+ 'Exclude some kinds of files and directories a la rsync(1). [+][*]') { |val|
132
133
  $diff.rsync_exclude = val
133
134
  }
134
135
  opts.on('--[no-]ignore-cvs-lines',
135
- 'Ignore CVS/RCS keyword lines. [!][*]') { |val|
136
+ 'Ignore CVS/RCS keyword lines. [+][*]') { |val|
136
137
  $diff.ignore_cvs_lines = val
137
138
  }
138
139
  opts.on('--[no-]fignore-exclude',
139
- 'Ignore files having suffixes specified in FIGNORE. [!][*]') { |val|
140
+ 'Ignore files having suffixes specified in FIGNORE. [+][*]') { |val|
140
141
  $diff.fignore_exclude = val
141
142
  }
142
143
  opts.on('-R', '--relative[=-]', miniTrueClass,
143
- 'Use relative path names. [*]') { |val|
144
+ 'Use relative path names.') { |val|
144
145
  $diff.relative = val
145
146
  }
146
147
  opts.on('-i', '--ignore-case[=-]', miniTrueClass,
@@ -189,19 +190,19 @@ usage: #{MYNAME} [flags] [files]
189
190
  set_format_flag('-C', val.to_s)
190
191
  }
191
192
  opts.on('-u[NUM]', '--unified[=NUM]', Integer,
192
- 'Output NUM (default 3) lines of unified context. [!]') { |val|
193
+ 'Output NUM (default 3) lines of unified context. [+]') { |val|
193
194
  set_format_flag('-U', val ? val.to_s : '3')
194
195
  }
195
196
  opts.on('-U NUM', Integer,
196
197
  'Output NUM lines of unified context.') { |val|
197
198
  set_format_flag('-U', val.to_s)
198
199
  }
199
- opts.on('-L LABEL', '--label=LABEL',
200
+ opts.on('--label=LABEL',
200
201
  'Use LABEL instead of file name.') { |val|
201
- set_flag('-L', val)
202
+ set_flag('--label', val)
202
203
  }
203
204
  opts.on('-p', '--show-c-function[=-]', miniTrueClass,
204
- 'Show which C function each change is in. [!]') { |val|
205
+ 'Show which C function each change is in. [+]') { |val|
205
206
  set_flag('-p', val)
206
207
  }
207
208
  opts.on('-F RE', '--show-function-line=RE',
@@ -252,37 +253,21 @@ usage: #{MYNAME} [flags] [files]
252
253
  'Output merged file to show `#ifdef NAME\' diffs.') { |val|
253
254
  set_format_flag('-D', val)
254
255
  }
255
- opts.on('--old-group-format=GFMT',
256
- 'Format old input groups with GFMT.') { |val|
257
- set_custom_format_flag('--old-group-format', val)
258
- }
259
- opts.on('--new-group-format=GFMT',
260
- 'Format new input groups with GFMT.') { |val|
261
- set_custom_format_flag('--new-group-format', val)
262
- }
263
- opts.on('--changed-group-format=GFMT',
264
- 'Format changed input groups with GFMT.') { |val|
265
- set_custom_format_flag('--changed-group-format', val)
266
- }
267
- opts.on('--unchanged-group-format=GFMT',
268
- 'Format unchanged input groups with GFMT.') { |val|
269
- set_custom_format_flag('--unchanged-group-format', val)
256
+ %w[old new changed unchanged].each { |gtype|
257
+ opts.on("--#{gtype}-group-format=GFMT",
258
+ "Format #{gtype} input groups with GFMT.") { |val|
259
+ set_custom_format_flag("--#{gtype}-group-format", val)
260
+ }
270
261
  }
271
262
  opts.on('--line-format=LFMT',
272
263
  'Format all input lines with LFMT.') { |val|
273
264
  set_custom_format_flag('--line-format', val)
274
265
  }
275
- opts.on('--old-line-format=LFMT',
276
- 'Format old input lines with LFMT.') { |val|
277
- set_custom_format_flag('--old-line-format', val)
278
- }
279
- opts.on('--new-line-format=LFMT',
280
- 'Format new input lines with LFMT.') { |val|
281
- set_custom_format_flag('--new-line-format', val)
282
- }
283
- opts.on('--unchanged-line-format=LFMT',
284
- 'Format unchanged input lines with LFMT.') { |val|
285
- set_custom_format_flag('--unchanged-line-format', val)
266
+ %w[old new changed unchanged].each { |ltype|
267
+ opts.on("--#{ltype}-line-format=LFMT",
268
+ "Format #{ltype} input lines with LFMT.") { |val|
269
+ set_custom_format_flag("--#{ltype}-line-format", val)
270
+ }
286
271
  }
287
272
  opts.on('-l', '--paginate[=-]', miniTrueClass,
288
273
  'Pass the output through `pr\' to paginate it.') { |val|
@@ -294,25 +279,30 @@ usage: #{MYNAME} [flags] [files]
294
279
  }
295
280
  opts.on('-T', '--initial-tab[=-]', miniTrueClass,
296
281
  'Make tabs line up by prepending a tab.') { |val|
297
- set_flag('-T', '--initial-tab', val)
282
+ set_flag('-T', val)
298
283
  }
299
284
  opts.on('--tabsize=NUM', Integer,
300
285
  'Tab stops are every NUM (default 8) print columns.') { |val|
301
286
  set_flag('--tabsize', val.to_s)
302
287
  }
288
+ opts.on('--suppress-blank-empty[=-]', miniTrueClass,
289
+ 'Suppress space or tab before empty output lines.') { |val|
290
+ set_flag('--suppress-blank-empty', val)
291
+ }
303
292
  opts.on('-r', '--recursive[=-]', miniTrueClass,
304
- 'Recursively compare any subdirectories found. [!]') { |val|
293
+ 'Recursively compare any subdirectories found. [+]') { |val|
305
294
  set_flag('-r', val)
306
295
  $diff.recursive = val
307
296
  }
308
297
  opts.on('-N', '--[no-]new-file[=-]', miniTrueClass,
309
- 'Treat absent files as empty. [!]') { |val|
298
+ 'Treat absent files as empty. [+]') { |val|
310
299
  set_flag('-N', val)
311
- $diff.new_file = val
300
+ $diff.new_file = val ? :bidirectional : val
312
301
  }
313
302
  opts.on('--unidirectional-new-file[=-]', miniTrueClass,
314
303
  'Treat absent first files as empty.') { |val|
315
304
  set_flag('--unidirectional-new-file', val)
305
+ $diff.new_file = val ? :unidirectional : val
316
306
  }
317
307
  opts.on('-s', '--report-identical-files[=-]', miniTrueClass,
318
308
  'Report when two files are the same.') { |val|
@@ -336,7 +326,7 @@ usage: #{MYNAME} [flags] [files]
336
326
  }
337
327
  opts.on('-S FILE', '--starting-file=FILE',
338
328
  'Start with FILE when comparing directories.') { |val|
339
- set_flag('-S', val)
329
+ $diff.starting_file = val
340
330
  }
341
331
  opts.on('--from-file=FILE1',
342
332
  'Compare FILE1 to all operands. FILE1 can be a directory.') { |val|
@@ -351,7 +341,7 @@ usage: #{MYNAME} [flags] [files]
351
341
  set_flag('--horizon-lines', val.to_s)
352
342
  }
353
343
  opts.on('-d', '--minimal[=-]', miniTrueClass,
354
- 'Try hard to find a smaller set of changes. [!]') { |val|
344
+ 'Try hard to find a smaller set of changes. [+]') { |val|
355
345
  set_flag('-d', val)
356
346
  }
357
347
  opts.on('--speed-large-files[=-]', miniTrueClass,
@@ -373,8 +363,8 @@ usage: #{MYNAME} [flags] [files]
373
363
  'Output this help.') { |val|
374
364
  invoke_pager
375
365
  print opts, <<EOS
376
- Options without the [*] sign will be passed through to diff(1).
377
- Options marked as [!] sign are turned on by default. To turn them off,
366
+ Options marked with [*] are this wrapper's original features.
367
+ Options marked with [+] are turned on by default. To turn them off,
378
368
  specify -?- for short options and --no-??? for long options, respectively.
379
369
 
380
370
  Environment variables:
@@ -466,23 +456,21 @@ def invoke_pager!
466
456
  pr.close
467
457
  pw.close
468
458
  IO.select([$stdin], nil, [$stdin])
469
- if system(ENV['PAGER'] || 'more')
470
- Process.kill(:TERM, ppid)
471
- else
459
+ begin
460
+ exec(ENV['PAGER'] || 'more')
461
+ rescue
472
462
  $stderr.puts "Pager failed."
473
- Process.kill(:INT, ppid)
474
463
  end
475
464
  }
476
- trap(:TERM) { exit(0) }
477
- trap(:INT) { exit(130) }
465
+
478
466
  $stdout.reopen(pw)
479
467
  $stderr.reopen(pw) if $stderr.tty?
480
468
  pw.close
481
469
  at_exit {
482
470
  $stdout.flush
483
471
  $stderr.flush
484
- $stdout.close
485
- $stderr.close
472
+ $stdout.reopen(IO::NULL)
473
+ $stderr.reopen(IO::NULL)
486
474
  Process.waitpid(pid)
487
475
  }
488
476
  end
@@ -543,7 +531,7 @@ def diff_main
543
531
  to_file = File.expand_path(from_file, to_file)
544
532
  end
545
533
 
546
- diff_dirs(from_file, to_file)
534
+ diff_dirs(from_file, to_file, true)
547
535
  else
548
536
  if $diff.relative
549
537
  from_file = File.expand_path(to_file, from_file)
@@ -607,9 +595,9 @@ def call_diff(*args)
607
595
  return status
608
596
  end
609
597
 
610
- def diff_dirs(dir1, dir2)
611
- entries1 = diff_entries(dir1)
612
- entries2 = diff_entries(dir2)
598
+ def diff_dirs(dir1, dir2, toplevel_p = false)
599
+ entries1 = diff_entries(dir1, toplevel_p)
600
+ entries2 = diff_entries(dir2, toplevel_p)
613
601
 
614
602
  common = entries1 & entries2
615
603
  missing1 = entries2 - entries1
@@ -635,15 +623,20 @@ def diff_dirs(dir1, dir2)
635
623
  end
636
624
 
637
625
  if $diff.reversed
638
- [[dir1, missing2], [dir2, missing1]]
626
+ [[dir1, missing2, true], [dir2, missing1, false]]
639
627
  else
640
- [[dir2, missing1], [dir1, missing2]]
641
- end.each { |dir, missing|
628
+ [[dir2, missing1, true], [dir1, missing2, false]]
629
+ end.each { |dir, missing, direction|
642
630
  new_files = []
631
+ case $diff.new_file
632
+ when :bidirectional
633
+ new_file = true
634
+ when :unidirectional
635
+ new_file = direction
636
+ end
643
637
  missing.each { |entry|
644
638
  file = File.join(dir, entry)
645
-
646
- if $diff.new_file
639
+ if new_file
647
640
  if File.directory?(file)
648
641
  if dir.equal?(dir1)
649
642
  diff_dirs(file, nil)
@@ -660,16 +653,21 @@ def diff_dirs(dir1, dir2)
660
653
  end
661
654
  }
662
655
  if dir.equal?(dir1)
663
- diff_files(new_files, EMPTYFILE)
656
+ diff_files(new_files, IO::NULL)
664
657
  else
665
- diff_files(EMPTYFILE, new_files)
658
+ diff_files(IO::NULL, new_files)
666
659
  end
667
660
  }
668
661
  end
669
662
 
670
- def diff_entries(dir)
663
+ def diff_entries(dir, toplevel_p)
671
664
  return [] if dir.nil?
672
- return Dir.entries(dir).reject { |file| diff_exclude?(dir, file) }
665
+ Dir.entries(dir).tap { |entries|
666
+ entries.reject! { |file| diff_exclude?(dir, file) }
667
+ if toplevel_p && (starting_file = $diff.starting_file)
668
+ entries.reject! { |file| file < starting_file }
669
+ end
670
+ }
673
671
  rescue => e
674
672
  warn "#{dir}: #{e}"
675
673
  return []
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: di
3
3
  version: !ruby/object:Gem::Version
4
- hash: 17
4
+ hash: 19
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
- - 2
9
8
  - 3
10
- version: 0.2.3
9
+ - 0
10
+ version: 0.3.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Akinori MUSHA
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2012-03-29 00:00:00 Z
18
+ date: 2012-05-14 00:00:00 Z
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
21
21
  name: thoughtbot-shoulda
@@ -85,7 +85,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
85
85
  requirements: []
86
86
 
87
87
  rubyforge_project:
88
- rubygems_version: 1.8.15
88
+ rubygems_version: 1.8.23
89
89
  signing_key:
90
90
  specification_version: 3
91
91
  summary: A wrapper around GNU diff(1)