di 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.
Files changed (4) hide show
  1. data/History.txt +3 -0
  2. data/README.txt +67 -0
  3. data/bin/di +545 -0
  4. metadata +55 -0
data/History.txt ADDED
@@ -0,0 +1,3 @@
1
+ == 0.1.1 2008-10-06
2
+
3
+ * Initial release
data/README.txt ADDED
@@ -0,0 +1,67 @@
1
+ = di
2
+
3
+ * http://www.idaemons.org/projects/di/
4
+
5
+ == DESCRIPTION:
6
+
7
+ di - a wrapper around GNU diff(1)
8
+
9
+ == FEATURES:
10
+
11
+ The di(1) command wraps around GNU diff(1) to provide reasonable
12
+ default settings and some original features:
13
+
14
+ - Ignore non-significant files, such as backup files, object files,
15
+ VCS administration files, etc. a la rsync(1)'s --cvs-ignore
16
+ option.
17
+
18
+ - Ignore difference of lines containing RCS tags.
19
+
20
+ - Output in unified format.
21
+
22
+ - Perform recursive comparison.
23
+
24
+ - Turn on some other useful options: -N -p -d.
25
+
26
+ - Provide the way to negate any of the above options.
27
+
28
+ == SYNOPSIS:
29
+
30
+ Run di --help for help.
31
+
32
+ == REQUIREMENTS:
33
+
34
+ - Ruby 1.8.6 or later
35
+
36
+ - GNU diff(1)
37
+
38
+ == INSTALL:
39
+
40
+ gem install di
41
+
42
+ == LICENSE:
43
+
44
+ Copyright (c) 2008 Akinori MUSHA
45
+
46
+ All rights reserved.
47
+
48
+ Redistribution and use in source and binary forms, with or without
49
+ modification, are permitted provided that the following conditions
50
+ are met:
51
+ 1. Redistributions of source code must retain the above copyright
52
+ notice, this list of conditions and the following disclaimer.
53
+ 2. Redistributions in binary form must reproduce the above copyright
54
+ notice, this list of conditions and the following disclaimer in the
55
+ documentation and/or other materials provided with the distribution.
56
+
57
+ THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
58
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
59
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
60
+ ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
61
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
62
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
63
+ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
64
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
65
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
66
+ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
67
+ SUCH DAMAGE.
data/bin/di ADDED
@@ -0,0 +1,545 @@
1
+ #!/usr/bin/env ruby
2
+ # -*- mode: ruby; coding: utf-8 -*-
3
+ #
4
+ # di - a wrapper around GNU diff(1)
5
+ #
6
+ # Copyright (c) 2008 Akinori MUSHA
7
+ #
8
+ # All rights reserved.
9
+ #
10
+ # Redistribution and use in source and binary forms, with or without
11
+ # modification, are permitted provided that the following conditions
12
+ # are met:
13
+ # 1. Redistributions of source code must retain the above copyright
14
+ # notice, this list of conditions and the following disclaimer.
15
+ # 2. Redistributions in binary form must reproduce the above copyright
16
+ # notice, this list of conditions and the following disclaimer in the
17
+ # documentation and/or other materials provided with the distribution.
18
+ #
19
+ # THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
20
+ # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22
+ # ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
23
+ # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24
+ # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25
+ # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26
+ # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27
+ # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28
+ # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29
+ # SUCH DAMAGE.
30
+ #
31
+ # $Id: di 69 2008-10-06 03:58:09Z knu $
32
+
33
+ MYVERSION = "0.1.1"
34
+ MYREVISION = %w$Rev: 69 $[1]
35
+ MYDATE = %w$Date: 2008-10-06 12:58:09 +0900 (Mon, 06 Oct 2008) $[1]
36
+ MYNAME = File.basename($0)
37
+
38
+ DIFF_CMD = ENV.fetch('DIFF', 'diff')
39
+ EMPTYFILE = '/dev/null'
40
+
41
+ RSYNC_EXCLUDE_GLOBS = %w(
42
+ RCS SCCS CVS CVS.adm
43
+ RCSLOG cvslog.* tags TAGS
44
+ .make.state .nse_depinfo *~
45
+ \#* .\#* ,* _$*
46
+ *$ *.old *.bak *.BAK
47
+ *.orig *.rej *.del-* *.a
48
+ *.olb *.o *.obj *.so
49
+ *.exe *.Z *.elc *.ln
50
+ core .svn .git .bzr .hg
51
+ )
52
+
53
+ FIGNORE_GLOBS = ENV.fetch('FIGNORE', '').split(':').map { |pat|
54
+ '*' + pat
55
+ }
56
+
57
+ def main(args)
58
+ setup
59
+
60
+ parse_args!(args)
61
+
62
+ diff_main
63
+
64
+ exit $status
65
+ end
66
+
67
+ def warn(*lines)
68
+ lines.each { |line|
69
+ STDERR.puts "#{MYNAME}: #{line}"
70
+ }
71
+ end
72
+
73
+ def setup
74
+ require 'ostruct'
75
+ $diff = OpenStruct.new
76
+ $diff.exclude = []
77
+ $diff.include = []
78
+ $diff.flags = []
79
+ end
80
+
81
+ def parse_args!(args)
82
+ require 'optparse'
83
+
84
+ banner = <<-"EOF"
85
+ #{MYNAME} - a wrapper around GNU diff(1)
86
+ version #{MYVERSION} [revision #{MYREVISION}] (#{MYDATE})
87
+
88
+ usage: #{MYNAME} [flags] [files]
89
+ EOF
90
+
91
+ opts = OptionParser.new(banner) { |opts|
92
+ miniTrueClass = Class.new
93
+ hash = OptionParser::CompletingHash.new
94
+ hash['-'] = false
95
+ opts.accept(miniTrueClass, hash) {|arg, val| val == nil or val}
96
+
97
+ opts.on('--[no-]rsync-exclude', '--[no-]cvs-exclude',
98
+ 'Exclude some kinds of files and directories a la rsync(1). [!][*]') { |val|
99
+ $diff.rsync_exclude = val
100
+ }
101
+ opts.on('--[no-]ignore-cvs-lines',
102
+ 'Ignore CVS keyword lines. [!][*]') { |val|
103
+ $diff.ignore_cvs_lines = val
104
+ }
105
+ opts.on('--[no-]fignore-exclude',
106
+ 'Ignore files having suffixes specified in FIGNORE. [!][*]') { |val|
107
+ $diff.fignore_exclude = val
108
+ }
109
+ opts.on('-R', '--relative[=-]', miniTrueClass,
110
+ 'Use relative path names. [*]') { |val|
111
+ $diff.relative = val
112
+ }
113
+ opts.on('-i', '--ignore-case[=-]', miniTrueClass,
114
+ 'Ignore case differences in file contents.') { |val|
115
+ set_flag('-i', val)
116
+ }
117
+ # not supported (yet)
118
+ #opts.on("--[no-]ignore-file-name-case",
119
+ # "Ignore case when comparing file names.") { |val|
120
+ # set_flag("--ignore-file-name-case", val)
121
+ #}
122
+ opts.on('-E', '--ignore-tab-expansion[=-]', miniTrueClass,
123
+ 'Ignore changes due to tab expansion.') { |val|
124
+ set_flag('-E', val)
125
+ }
126
+ opts.on('-b', '--ignore-space-change[=-]', miniTrueClass,
127
+ 'Ignore changes in the amount of white space.') { |val|
128
+ set_flag('-b', val)
129
+ }
130
+ opts.on('-w', '--ignore-all-space[=-]', miniTrueClass,
131
+ 'Ignore all white space.') { |val|
132
+ set_flag('-w', val)
133
+ }
134
+ opts.on('-B', '--ignore-blank-lines[=-]', miniTrueClass,
135
+ 'Ignore changes whose lines are all blank.') { |val|
136
+ set_flag('-B', val)
137
+ }
138
+ opts.on('-I RE', '--ignore-matching-lines=RE',
139
+ 'Ignore changes whose lines all match RE.') { |val|
140
+ set_flag('-I', val)
141
+ }
142
+ opts.on('--[no-]strip-trailing-cr',
143
+ 'Strip trailing carriage return on input.') { |val|
144
+ set_flag('--strip-trailing-cr', val)
145
+ }
146
+ opts.on('-a', '--text[=-]', miniTrueClass,
147
+ 'Treat all files as text.') { |val|
148
+ set_flag('-a', val)
149
+ }
150
+ opts.on('-c[NUM]', '--context[=NUM]', Integer,
151
+ 'Output NUM (default 3) lines of copied context.') { |val|
152
+ $diff.format = ['-C', val ? val.to_s : '3']
153
+ }
154
+ opts.on('-C NUM', Integer,
155
+ 'Output NUM lines of copied context.') { |val|
156
+ $diff.format = ['-C', val.to_s]
157
+ }
158
+ opts.on('-u[NUM]', '--unified[=NUM]', Integer,
159
+ 'Output NUM (default 3) lines of unified context. [!]') { |val|
160
+ $diff.format = ['-U', val ? val.to_s : '3']
161
+ }
162
+ opts.on('-U NUM', Integer,
163
+ 'Output NUM lines of unified context.') { |val|
164
+ $diff.format = ['-U', val.to_s]
165
+ }
166
+ opts.on('-L LABEL', '--label=LABEL',
167
+ 'Use LABEL instead of file name.') { |val|
168
+ set_flag('-L', val)
169
+ }
170
+ opts.on('-p', '--show-c-function[=-]', miniTrueClass,
171
+ 'Show which C function each change is in. [!]') { |val|
172
+ set_flag('-p', val)
173
+ }
174
+ opts.on('-F RE', '--show-function-line=RE',
175
+ 'Show the most recent line matching RE.') { |val|
176
+ set_flag('-F', val)
177
+ }
178
+ opts.on('-q', '--brief[=-]', miniTrueClass,
179
+ 'Output only whether files differ.') { |val|
180
+ set_flag('-q', val)
181
+ }
182
+ opts.on('-e', '--ed[=-]', miniTrueClass,
183
+ 'Output an ed script.') { |val|
184
+ if val
185
+ $diff.format = ['-e', val]
186
+ end
187
+ }
188
+ opts.on('--normal[=-]', miniTrueClass,
189
+ 'Output a normal diff.') { |val|
190
+ if val
191
+ $diff.format = ['--normal', val]
192
+ end
193
+ }
194
+ opts.on('-n', '--rcs[=-]', miniTrueClass,
195
+ 'Output an RCS format diff.') { |val|
196
+ if val
197
+ $diff.format = ['-n', val]
198
+ end
199
+ }
200
+ opts.on('-y', '--side-by-side[=-]', miniTrueClass,
201
+ 'Output in two columns.') { |val|
202
+ if val
203
+ $diff.format = ['-y', val]
204
+ end
205
+ }
206
+ opts.on('-W NUM', '--width=NUM', Integer,
207
+ 'Output at most NUM (default 130) print columns.') { |val|
208
+ set_flag('-W', val.to_s)
209
+ }
210
+ opts.on('--left-column[=-]', miniTrueClass,
211
+ 'Output only the left column of common lines.') { |val|
212
+ set_flag('--left-column', val)
213
+ }
214
+ opts.on('--suppress-common-lines[=-]', miniTrueClass,
215
+ 'Do not output common lines.') { |val|
216
+ set_flag('--suppress-common-lines', val)
217
+ }
218
+ opts.on('-D NAME', '--ifdef=NAME',
219
+ 'Output merged file to show `#ifdef NAME\' diffs.') { |val|
220
+ set_flag('-D', val)
221
+ }
222
+ opts.on('--old-group-format=GFMT',
223
+ 'Format old input groups with GFMT.') { |val|
224
+ set_flag('--old-group-format', val)
225
+ }
226
+ opts.on('--new-group-format=GFMT',
227
+ 'Format new input groups with GFMT.') { |val|
228
+ set_flag('--new-group-format', val)
229
+ }
230
+ opts.on('--unchanged-group-format=GFMT',
231
+ 'Format unchanged input groups with GFMT.') { |val|
232
+ set_flag('--unchanged-group-format', val)
233
+ }
234
+ opts.on('--line-format=LFMT',
235
+ 'Format all input lines with LFMT.') { |val|
236
+ set_flag('--line-format', val)
237
+ }
238
+ opts.on('--old-line-format=LFMT',
239
+ 'Format old input lines with LFMT.') { |val|
240
+ set_flag('--old-line-format', val)
241
+ }
242
+ opts.on('--new-line-format=LFMT',
243
+ 'Format new input lines with LFMT.') { |val|
244
+ set_flag('--new-line-format', val)
245
+ }
246
+ opts.on('--unchanged-line-format=LFMT',
247
+ 'Format unchanged input lines with LFMT.') { |val|
248
+ set_flag('--unchanged-line-format', val)
249
+ }
250
+ opts.on('-l', '--paginate[=-]', miniTrueClass,
251
+ 'Pass the output through `pr\' to paginate it.') { |val|
252
+ set_flag('-l', val)
253
+ }
254
+ opts.on('-t', '--expand-tabs[=-]', miniTrueClass,
255
+ 'Expand tabs to spaces in output.') { |val|
256
+ set_flag('-t', val)
257
+ }
258
+ opts.on('-T', '--initial-tab[=-]', miniTrueClass,
259
+ 'Make tabs line up by prepending a tab.') { |val|
260
+ set_flag('-T', '--initial-tab', val)
261
+ }
262
+ opts.on('--tabsize=NUM', Integer,
263
+ 'Tab stops are every NUM (default 8) print columns.') { |val|
264
+ set_flag('--tabsize', val.to_s)
265
+ }
266
+ opts.on('-r', '--recursive[=-]', miniTrueClass,
267
+ 'Recursively compare any subdirectories found. [!]') { |val|
268
+ set_flag('-r', val)
269
+ $diff.recursive = val
270
+ }
271
+ opts.on('-N', '--[no-]new-file[=-]', miniTrueClass,
272
+ 'Treat absent files as empty. [!]') { |val|
273
+ set_flag('-N', val)
274
+ $diff.new_file = val
275
+ }
276
+ opts.on('--unidirectional-new-file[=-]', miniTrueClass,
277
+ 'Treat absent first files as empty.') { |val|
278
+ set_flag('--unidirectional-new-file', val)
279
+ }
280
+ opts.on('-s', '--report-identical-files[=-]', miniTrueClass,
281
+ 'Report when two files are the same.') { |val|
282
+ set_flag('-s', val)
283
+ }
284
+ opts.on('-x PAT', '--exclude=PAT',
285
+ 'Exclude files that match PAT.') { |val|
286
+ $diff.exclude << val
287
+ }
288
+ opts.on('-X FILE', '--exclude-from=FILE',
289
+ 'Exclude files that match any pattern in FILE.') { |val|
290
+ if val == '-'
291
+ $diff.exclude.concat(STDIN.read.split(/\n/))
292
+ else
293
+ $diff.exclude.concat(File.read(val).split(/\n/))
294
+ end
295
+ }
296
+ opts.on('--include=PAT',
297
+ 'Do not exclude files that match PAT.') { |val|
298
+ $diff.include << val
299
+ }
300
+ opts.on('-S FILE', '--starting-file=FILE',
301
+ 'Start with FILE when comparing directories.') { |val|
302
+ set_flag('-S', val)
303
+ }
304
+ opts.on('--from-file=FILE1',
305
+ 'Compare FILE1 to all operands. FILE1 can be a directory.') { |val|
306
+ $diff.from_files = [val]
307
+ }
308
+ opts.on('--to-file=FILE2',
309
+ 'Compare all operands to FILE2. FILE2 can be a directory.') { |val|
310
+ $diff.to_files = [val]
311
+ }
312
+ opts.on('--horizon-lines=NUM', Integer,
313
+ 'Keep NUM lines of the common prefix and suffix.') { |val|
314
+ set_flag('--horizon-lines', val.to_s)
315
+ }
316
+ opts.on('-d', '--minimal[=-]', miniTrueClass,
317
+ 'Try hard to find a smaller set of changes. [!]') { |val|
318
+ set_flag('-d', val)
319
+ }
320
+ opts.on('--speed-large-files[=-]', miniTrueClass,
321
+ 'Assume large files and many scattered small changes.') { |val|
322
+ set_flag('--speed-large-files', val)
323
+ }
324
+ opts.on('-v', '--version',
325
+ 'Output version info.') { |val|
326
+ set_flag('-v', val)
327
+ }
328
+ opts.on('--help',
329
+ 'Output this help.') { |val|
330
+ print opts,
331
+ "\n",
332
+ "Options without the [*] sign will be passed through to diff(1).\n",
333
+ "Options marked as [!] sign are turned on by default. To turn them off,\n",
334
+ "specify -?- for short options and --no-??? for long options, respectively.\n"
335
+ exit 0
336
+ }
337
+ }
338
+
339
+ begin
340
+ opts.parse('--rsync-exclude', '--fignore-exclude', '--ignore-cvs-lines',
341
+ '-N', '-r', '-p', '-d')
342
+ opts.parse!(args)
343
+
344
+ $diff.format ||= ['-U', '3']
345
+ set_flag(*$diff.format)
346
+
347
+ if $diff.ignore_cvs_lines
348
+ opts.parse('--ignore-matching-lines=\$[A-Z][A-Za-z0-9][A-Za-z0-9]*\(:.*\)\{0,1\}\$')
349
+ end
350
+ rescue OptionParser::ParseError => e
351
+ warn e, "Try `#{MYNAME} --help' for more information."
352
+ exit 64
353
+ rescue => e
354
+ warn e
355
+ exit 1
356
+ end
357
+
358
+ begin
359
+ if $diff.from_files
360
+ $diff.to_files ||= args.dup
361
+
362
+ if $diff.to_files.empty?
363
+ raise "missing operand"
364
+ end
365
+ elsif $diff.to_files
366
+ $diff.from_files = args.dup
367
+
368
+ if $diff.from_files.empty?
369
+ raise "missing operand"
370
+ end
371
+ else
372
+ if args.size < 2
373
+ raise "missing operand"
374
+ end
375
+
376
+ if File.directory?(args[0])
377
+ $diff.to_files = args.dup
378
+ $diff.from_files = [$diff.to_files.shift]
379
+ else
380
+ $diff.from_files = args.dup
381
+ $diff.to_files = [$diff.from_files.pop]
382
+ end
383
+ end
384
+
385
+ if $diff.from_files.size != 1 && $diff.to_files.size != 1
386
+ raise "wrong number of files given"
387
+ end
388
+ rescue => e
389
+ warn e, "Try `#{MYNAME} --help' for more information."
390
+ exit 64
391
+ end
392
+ end
393
+
394
+ def set_flag(flag, val)
395
+ case val
396
+ when false
397
+ $diff.flags.reject! { |f,| f == flag }
398
+ when true
399
+ $diff.flags.reject! { |f,| f == flag }
400
+ $diff.flags << [flag]
401
+ else
402
+ $diff.flags << [flag, val]
403
+ end
404
+ end
405
+
406
+ def diff_main
407
+ $status = 0
408
+
409
+ $diff.from_files.each { |from_file|
410
+ if File.directory?(from_file)
411
+ $diff.to_files.each { |to_file|
412
+ if File.directory?(to_file)
413
+ if $diff.relative
414
+ to_file = File.expand_path(from_file, to_file)
415
+ end
416
+
417
+ diff_dirs(from_file, to_file)
418
+ else
419
+ if $diff.relative
420
+ from_file = File.expand_path(to_file, from_file)
421
+ else
422
+ from_file = File.expand_path(File.basename(to_file), from_file)
423
+ end
424
+
425
+ diff_files(from_file, to_file)
426
+ end
427
+ }
428
+ else
429
+ $diff.to_files.each { |to_file|
430
+ if File.directory?(to_file)
431
+ if $diff.relative
432
+ to_file = File.expand_path(from_file, to_file)
433
+ else
434
+ to_file = File.expand_path(File.basename(from_file), to_file)
435
+ end
436
+ end
437
+
438
+ diff_files(from_file, to_file)
439
+ }
440
+ end
441
+ }
442
+ end
443
+
444
+ def diff_files(file1, file2)
445
+ if file1.is_a?(Array)
446
+ file2.is_a?(Array) and raise "cannot compare two sets of multiple files"
447
+ file1.empty? and return 0
448
+
449
+ call_diff('--to-file', file2, file1)
450
+ elsif file2.is_a?(Array)
451
+ file1.empty? and return 0
452
+
453
+ call_diff('--from-file', file1, file2)
454
+ else
455
+ call_diff(file1, file2)
456
+ end
457
+ end
458
+
459
+ def call_diff(*args)
460
+ system(*[DIFF_CMD, $diff.flags, args].flatten)
461
+ status = $? >> 8
462
+ $status = status if $status < status
463
+ return status
464
+ end
465
+
466
+ def diff_dirs(dir1, dir2)
467
+ entries1 = diff_entries(dir1)
468
+ entries2 = diff_entries(dir2)
469
+
470
+ common = entries1 & entries2
471
+ missing1 = entries2 - entries1
472
+ missing2 = entries1 - entries2
473
+
474
+ files = []
475
+ common.each { |file|
476
+ file1 = File.join(dir1, file)
477
+ file2 = File.join(dir2, file)
478
+ file1_is_dir = File.directory?(file1)
479
+ file2_is_dir = File.directory?(file2)
480
+ if file1_is_dir && file2_is_dir
481
+ diff_dirs(file1, file2) if $diff.recursive
482
+ elsif !file1_is_dir && !file2_is_dir
483
+ files << file1
484
+ else
485
+ missing1 << file
486
+ missing2 << file
487
+ end
488
+ }
489
+ diff_files(files, dir2)
490
+
491
+ [[dir1, missing2], [dir2, missing1]].each { |dir, missing|
492
+ new_files = []
493
+ missing.each { |entry|
494
+ file = File.join(dir, entry)
495
+
496
+ if $diff.new_file
497
+ if File.directory?(file)
498
+ if dir.equal?(dir1)
499
+ diff_dirs(file, nil)
500
+ else
501
+ diff_dirs(nil, file)
502
+ end
503
+ else
504
+ new_files << file
505
+ end
506
+ else
507
+ printf "Only in %s: %s (%s)\n",
508
+ dir, entry, File.directory?(file) ? 'directory' : 'file'
509
+ $status = 1 if $status < 1
510
+ end
511
+ }
512
+ if dir.equal?(dir1)
513
+ diff_files(new_files, EMPTYFILE)
514
+ else
515
+ diff_files(EMPTYFILE, new_files)
516
+ end
517
+ }
518
+ end
519
+
520
+ def diff_entries(dir)
521
+ return [] if dir.nil?
522
+ return Dir.entries(dir).reject { |file| diff_exclude?(file) }
523
+ rescue => e
524
+ warn "#{dir}: #{e}"
525
+ return []
526
+ end
527
+
528
+ def diff_exclude?(basename)
529
+ return true if basename == '.' || basename == '..'
530
+ return false if $diff.include.any? { |pat|
531
+ File.fnmatch(pat, basename, File::FNM_DOTMATCH)
532
+ }
533
+ return true if $diff.exclude.any? { |pat|
534
+ File.fnmatch(pat, basename, File::FNM_DOTMATCH)
535
+ }
536
+ return true if $diff.rsync_exclude && RSYNC_EXCLUDE_GLOBS.any? { |pat|
537
+ File.fnmatch(pat, basename, File::FNM_DOTMATCH)
538
+ }
539
+ return true if $diff.fignore_exclude && FIGNORE_GLOBS.any? { |pat|
540
+ File.fnmatch(pat, basename, File::FNM_DOTMATCH)
541
+ }
542
+ return false
543
+ end
544
+
545
+ main(ARGV)
metadata ADDED
@@ -0,0 +1,55 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: di
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.1
5
+ platform: ruby
6
+ authors:
7
+ - Akinori MUSHA
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2008-10-06 00:00:00 +09:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description:
17
+ email: knu@idaemons.org
18
+ executables:
19
+ - di
20
+ extensions: []
21
+
22
+ extra_rdoc_files: []
23
+
24
+ files:
25
+ - bin/di
26
+ - README.txt
27
+ - History.txt
28
+ has_rdoc: false
29
+ homepage: http://www.idaemons.org/projects/di/
30
+ post_install_message:
31
+ rdoc_options: []
32
+
33
+ require_paths:
34
+ - lib
35
+ required_ruby_version: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ">="
38
+ - !ruby/object:Gem::Version
39
+ version: "0"
40
+ version:
41
+ required_rubygems_version: !ruby/object:Gem::Requirement
42
+ requirements:
43
+ - - ">="
44
+ - !ruby/object:Gem::Version
45
+ version: "0"
46
+ version:
47
+ requirements: []
48
+
49
+ rubyforge_project: unixutils
50
+ rubygems_version: 1.0.1
51
+ signing_key:
52
+ specification_version: 2
53
+ summary: A wrapper around GNU diff(1)
54
+ test_files: []
55
+