pvn 0.0.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 (99) hide show
  1. data/README.markdown +38 -0
  2. data/bin/pvn +12 -0
  3. data/bin/pvndiff +10 -0
  4. data/lib/pvn/app.rb +144 -0
  5. data/lib/pvn/base/textlines.rb +35 -0
  6. data/lib/pvn/base/util.rb +14 -0
  7. data/lib/pvn/cmddoc.rb +77 -0
  8. data/lib/pvn/config.rb +65 -0
  9. data/lib/pvn/describe.rb +40 -0
  10. data/lib/pvn/diff/diffcmd.rb +49 -0
  11. data/lib/pvn/diff/differ.rb +67 -0
  12. data/lib/pvn/diff/diffopts.rb +58 -0
  13. data/lib/pvn/doc.rb +34 -0
  14. data/lib/pvn/io/element.rb +113 -0
  15. data/lib/pvn/io/fselement.rb +22 -0
  16. data/lib/pvn/log/formatter/color_formatter.rb +29 -0
  17. data/lib/pvn/log/formatter/entries_formatter.rb +33 -0
  18. data/lib/pvn/log/formatter/entry_formatter.rb +57 -0
  19. data/lib/pvn/log/formatter/log_formatter.rb +59 -0
  20. data/lib/pvn/log/formatter/message_formatter.rb +19 -0
  21. data/lib/pvn/log/formatter/path_formatter.rb +41 -0
  22. data/lib/pvn/log/formatter/summary_formatter.rb +49 -0
  23. data/lib/pvn/log/logcmd.rb +136 -0
  24. data/lib/pvn/log/logentry.rb +116 -0
  25. data/lib/pvn/log/logfactory.rb +101 -0
  26. data/lib/pvn/log/logoptions.rb +43 -0
  27. data/lib/pvn/pct/linecount.rb +33 -0
  28. data/lib/pvn/pct/pctcmd.rb +204 -0
  29. data/lib/pvn/pct/statcmd.rb +13 -0
  30. data/lib/pvn/revision/entry.rb +94 -0
  31. data/lib/pvn/revision.rb +119 -0
  32. data/lib/pvn/subcommands/base/clargs.rb +53 -0
  33. data/lib/pvn/subcommands/base/command.rb +60 -0
  34. data/lib/pvn/subcommands/base/doc.rb +94 -0
  35. data/lib/pvn/subcommands/base/options.rb +22 -0
  36. data/lib/pvn/subcommands/log/command.rb +70 -0
  37. data/lib/pvn/subcommands/log/options.rb +43 -0
  38. data/lib/pvn/subcommands/pct/clargs.rb +33 -0
  39. data/lib/pvn/subcommands/pct/command.rb +57 -0
  40. data/lib/pvn/subcommands/revision/multiple_revisions_option.rb +43 -0
  41. data/lib/pvn/subcommands/revision/revision_option.rb +74 -0
  42. data/lib/pvn/subcommands/revision/revision_regexp_option.rb +39 -0
  43. data/lib/pvn/svn/command/svncmd.rb +39 -0
  44. data/lib/pvn/svn/environment.rb +23 -0
  45. data/lib/pvn/svn/svnelement.rb +89 -0
  46. data/lib/pvn/svn/svninfo.rb +42 -0
  47. data/lib/pvn/svn/svnroot.rb +29 -0
  48. data/lib/pvn/upp/uppcmd.rb +112 -0
  49. data/lib/pvn/wherecmd.rb +55 -0
  50. data/lib/pvn.rb +8 -0
  51. data/lib/svnx/command.rb +60 -0
  52. data/lib/svnx/entry.rb +34 -0
  53. data/lib/svnx/info/command.rb +21 -0
  54. data/lib/svnx/info/entries.rb +27 -0
  55. data/lib/svnx/info/entry.rb +34 -0
  56. data/lib/svnx/log/command.rb +93 -0
  57. data/lib/svnx/log/entries.rb +57 -0
  58. data/lib/svnx/log/entry.rb +54 -0
  59. data/lib/svnx/status/command.rb +21 -0
  60. data/lib/svnx/status/entries.rb +22 -0
  61. data/lib/svnx/status/entry.rb +33 -0
  62. data/lib/synoption/base_option.rb +149 -0
  63. data/lib/synoption/boolean_option.rb +21 -0
  64. data/lib/synoption/doc.rb +81 -0
  65. data/lib/synoption/fixnum_option.rb +13 -0
  66. data/lib/synoption/match.rb +47 -0
  67. data/lib/synoption/option.rb +10 -0
  68. data/lib/synoption/optionable.rb +66 -0
  69. data/lib/synoption/set.rb +114 -0
  70. data/lib/system/cachecmd.rb +65 -0
  71. data/lib/system/cmdexec.rb +13 -0
  72. data/lib/system/cmdline.rb +70 -0
  73. data/lib/system/command/arg.rb +12 -0
  74. data/lib/system/command/cachefile.rb +39 -0
  75. data/lib/system/command/caching.rb +36 -0
  76. data/lib/system/command/line.rb +47 -0
  77. data/lib/system/command.rb +72 -0
  78. data/test/integration/svnx/log/test.rb +43 -0
  79. data/test/unit/pvn/app_test.rb +22 -0
  80. data/test/unit/pvn/io/element/log/log_test.rb +35 -0
  81. data/test/unit/pvn/log/formatter/entry_formatter_test.rb +90 -0
  82. data/test/unit/pvn/revision/entry_test.rb +123 -0
  83. data/test/unit/pvn/subcommands/log/command_test.rb +22 -0
  84. data/test/unit/pvn/subcommands/log/options_test.rb +85 -0
  85. data/test/unit/pvn/subcommands/revision/multiple_revisions_option_test.rb +67 -0
  86. data/test/unit/pvn/subcommands/revision/revision_option_test.rb +57 -0
  87. data/test/unit/pvn/subcommands/revision/revision_regexp_option_test.rb +69 -0
  88. data/test/unit/svnx/info/entry_test.rb +52 -0
  89. data/test/unit/svnx/log/cmargs_test.rb +22 -0
  90. data/test/unit/svnx/log/entries_test.rb +73 -0
  91. data/test/unit/svnx/log/entry_test.rb +21 -0
  92. data/test/unit/svnx/status/entry_test.rb +39 -0
  93. data/test/unit/synoption/base_option_test.rb +182 -0
  94. data/test/unit/synoption/match_test.rb +61 -0
  95. data/test/unit/synoption/option_test.rb +15 -0
  96. data/test/unit/synoption/set_test.rb +37 -0
  97. data/test/unit/system/command/caching_test.rb +97 -0
  98. data/test/unit/system/command/line_test.rb +33 -0
  99. metadata +199 -0
data/README.markdown ADDED
@@ -0,0 +1,38 @@
1
+ PVN
2
+ ===
3
+
4
+ Pvn adds functionality stolen and inspired by Perforce and Git, as well as just
5
+ things I conjured up.
6
+
7
+ What it isn't: a replace for svn (the command). The intent here is not to do
8
+ everything svn does, but better. Maybe some day that will happen.
9
+
10
+ SUMMARY
11
+ -------
12
+
13
+ svn [ options ] file ...
14
+
15
+ FEATURES
16
+ --------
17
+
18
+ **Relative revisions**: Pvn supports revisions being specified as being relative
19
+ to their "index" in the list of svn revision. "+n" means the nth revision in
20
+ the list for a given path, and "-n" is the nth from the last revision, where
21
+ -1 means the last revision.
22
+
23
+ Thus for the following list of revisions for a path:
24
+
25
+ r1947 | easter.bunny | 2011-11-14 07:24:45 -0500 (Mon, 14 Nov 2011) | 1 line
26
+ r1714 | santa.claus | 2011-09-22 16:38:30 -0400 (Thu, 22 Sep 2011) | 1 line
27
+ r1192 | santa.claus | 2011-09-05 03:51:04 -0400 (Mon, 05 Sep 2011) | 1 line
28
+ r1145 | tooth.fairy | 2011-08-02 04:57:23 -0400 (Tue, 02 Aug 2011) | 1 line
29
+ r1143 | santa.claus | 2011-07-29 07:51:49 -0400 (Fri, 29 Jul 2011) | 1 line
30
+ r1049 | santa.claus | 2011-06-22 07:17:43 -0400 (Wed, 22 Jun 2011) | 1 line
31
+
32
+ Relative revision +0 is r1049, -1 is r1947, +1 is r1143, and so on.
33
+
34
+ **Colorized logging**. The "log" subcommand works in pvn as it does with svn,
35
+ except that output is colorized, differing for the elements (file, directory) and
36
+ the status of the element (added, deleted, changed). The logging output also
37
+ shows the relative revision.
38
+
data/bin/pvn ADDED
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # Created on 2011-11-9.
4
+ # Copyright (c) 2011. All rights reserved.
5
+
6
+ require 'rubygems'
7
+ require File.expand_path(File.dirname(__FILE__) + "/../lib/pvn")
8
+ require "pvn/app"
9
+
10
+ PVN::App::Runner.new STDOUT, ARGV
11
+
12
+ # PVN::App.execute(STDOUT, ARGV)
data/bin/pvndiff ADDED
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # Created on 2011-11-9.
4
+ # Copyright (c) 2011. All rights reserved.
5
+
6
+ require 'rubygems'
7
+ require File.expand_path(File.dirname(__FILE__) + "/../lib/pvn")
8
+ require "pvn/diff/differ"
9
+
10
+ PVN::Differ.new ARGV
data/lib/pvn/app.rb ADDED
@@ -0,0 +1,144 @@
1
+ #!/usr/bin/ruby -w
2
+ # -*- ruby -*-
3
+
4
+ require 'rubygems'
5
+ require 'riel'
6
+
7
+ require 'pvn/io/element'
8
+
9
+ require 'svnx/log/entries'
10
+
11
+ require 'pvn/subcommands/log/command'
12
+
13
+ # not yet supported:
14
+ # require 'pvn/subcommands/pct/command'
15
+
16
+ # the old ones:
17
+ require 'pvn/diff/diffcmd'
18
+ require 'pvn/pct/pctcmd'
19
+ require 'pvn/describe'
20
+ require 'pvn/upp/uppcmd'
21
+ require 'pvn/wherecmd'
22
+
23
+ module PVN; module App; end; end
24
+
25
+ module PVN::App
26
+ class Runner
27
+ include Loggable
28
+
29
+ def initialize io, args
30
+ RIEL::Log.level = RIEL::Log::WARN
31
+ RIEL::Log.set_widths(-25, 5, -35)
32
+
33
+ if args.empty?
34
+ run_help args
35
+ end
36
+
37
+ while args.size > 0
38
+ arg = args.shift
39
+ info "arg: #{arg}"
40
+
41
+ case arg
42
+ when "--verbose"
43
+ RIEL::Log.level = RIEL::Log::DEBUG
44
+ when "help", "--help", "-h"
45
+ run_help args
46
+ when "log"
47
+ run_command PVN::Subcommands::Log::Command, args
48
+ when "pct"
49
+ $stderr.puts "subcommand 'pct' is not yet supported"
50
+ exit(-1)
51
+ else
52
+ $stderr.puts "ERROR: subcommand not valid: #{arg}"
53
+ exit(-1)
54
+ end
55
+ end
56
+
57
+ run_help args
58
+ end
59
+
60
+ def run_command cmdcls, args
61
+ begin
62
+ cmdcls.new args
63
+ exit(0)
64
+ rescue => e
65
+ # puts e.backtrace
66
+ $stderr.puts e
67
+ exit(-1)
68
+ end
69
+ end
70
+
71
+ # below is the old implementation. yes, I should have branched this.
72
+ # =======================================================
73
+
74
+ def self.run_command_with_output cmd
75
+ RIEL::Log.info "cmd: #{cmd}".on_black
76
+ puts cmd.output
77
+ true
78
+ end
79
+
80
+ def self.run_command_as_entries cmd
81
+ RIEL::Log.info "cmd: #{cmd}".on_black
82
+ cmd.write_entries
83
+ true
84
+ end
85
+
86
+ SUBCOMMANDS = [ PVN::Subcommands::Log::Command,
87
+ # DiffCommand,
88
+ # DescribeCommand,
89
+ # PctCommand,
90
+ # WhereCommand,
91
+ # UndeleteCommand,
92
+ ]
93
+
94
+ def run_help args
95
+ forwhat = args[0]
96
+
97
+ cls = SUBCOMMANDS.find do |cls|
98
+ cls.getdoc.subcommands.include? forwhat
99
+ end
100
+
101
+ if cls
102
+ cls.to_doc
103
+ else
104
+ puts "usage: pvn [--verbose] <command> [<options>] [<args>]"
105
+ puts "PVN, version #{PVN::VERSION}"
106
+ puts
107
+ puts "PVN has the subcommands:"
108
+ SUBCOMMANDS.each do |sc|
109
+ printf " %-10s %s\n", sc.getdoc.subcommands[0], sc.getdoc.description
110
+ end
111
+ end
112
+ exit(0)
113
+ end
114
+
115
+ def self.execute stdout, args = Array.new
116
+ while args.size > 0
117
+ arg = args.shift
118
+ RIEL::Log.debug "arg: #{arg}"
119
+
120
+ if arg == "--verbose"
121
+ RIEL::Log.level = RIEL::Log::DEBUG
122
+ next
123
+ end
124
+
125
+ if arg == "help"
126
+ return run_help args
127
+ end
128
+
129
+ SUBCOMMANDS.each do |sc|
130
+ if sc.doc.subcommands.include?(arg)
131
+ cmd = sc.new :execute => true, :command_args => args
132
+ if cmd.has_entries?
133
+ return run_command_as_entries cmd
134
+ else
135
+ return run_command_with_output cmd
136
+ end
137
+ end
138
+ end
139
+
140
+ $stderr.puts "ERROR: subcommand not valid: #{arg}"
141
+ end
142
+ end
143
+ end
144
+ end
@@ -0,0 +1,35 @@
1
+ #!/usr/bin/ruby -w
2
+ # -*- ruby -*-
3
+
4
+ require 'rubygems'
5
+ require 'riel'
6
+
7
+ module PVN
8
+ class TextLines
9
+ include Loggable
10
+
11
+ attr_reader :lines
12
+
13
+ def initialize lines
14
+ @lines = lines
15
+ @lidx = 0
16
+ end
17
+
18
+ def match_line re, offset = 0
19
+ re.match line(offset)
20
+ end
21
+
22
+ def line offset = 0
23
+ @lines[@lidx + offset]
24
+ end
25
+
26
+ def has_line?
27
+ @lidx < @lines.length
28
+ end
29
+
30
+ def advance_line offset = 1
31
+ @lidx += offset
32
+ end
33
+
34
+ end
35
+ end
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/ruby -w
2
+ # -*- ruby -*-
3
+
4
+ module PVN
5
+ module Util
6
+ POS_NEG_NUMERIC_RE = Regexp.new('^[\-\+]?\d+$')
7
+
8
+ # Returns the list joined by spaces, with each element in the list in double
9
+ # quotes.
10
+ def self.quote_list args
11
+ args.collect { |a| "\"#{a}\"" }.join(' ')
12
+ end
13
+ end
14
+ end
data/lib/pvn/cmddoc.rb ADDED
@@ -0,0 +1,77 @@
1
+ #!/usr/bin/ruby -w
2
+ # -*- ruby -*-
3
+
4
+ require 'rubygems'
5
+ require 'riel'
6
+
7
+ module PVN
8
+ class CommandDoc
9
+ attr_accessor :subcommands
10
+ attr_accessor :description
11
+ attr_accessor :usage
12
+ attr_accessor :summary
13
+
14
+ attr_reader :examples
15
+ attr_reader :options
16
+
17
+ def initialize
18
+ @subcommands = nil
19
+ @description = nil
20
+ @usage = nil
21
+ @summary = nil
22
+ @options = Array.new
23
+ @examples = Array.new
24
+ end
25
+
26
+ def to_doc io = $stdout
27
+ doc = Array.new
28
+
29
+ subcmds = @subcommands
30
+
31
+ subcmdstr = subcmds[0].dup
32
+ if subcmds.size > 1
33
+ subcmdstr << " (" << subcmds[1 .. -1].join(" ") << ")"
34
+ end
35
+
36
+ io.puts subcmdstr + ": " + @description
37
+ io.puts "usage: " + subcmds[0] + " " + @usage
38
+ io.puts ""
39
+ io.puts @summary.collect { |line| " " + line }
40
+
41
+ write_section "options", @options, io do |opt, io|
42
+ option_to_doc opt, io
43
+ end
44
+
45
+ write_section "examples", @examples, io do |ex, io|
46
+ example_to_doc ex, io
47
+ end
48
+ end
49
+
50
+ def write_section name, section, io
51
+ if section.length > 0
52
+ io.puts ""
53
+ io.puts "#{name.capitalize}:"
54
+ io.puts ""
55
+
56
+ section.each do |opt|
57
+ yield opt, io
58
+ end
59
+ end
60
+ end
61
+
62
+ def example_to_doc ex, io
63
+ ex.each_with_index do |line, idx|
64
+ if idx == 0
65
+ io.puts " % #{line}"
66
+ else
67
+ io.puts " #{line}"
68
+ end
69
+ end
70
+ io.puts
71
+ end
72
+
73
+ def option_to_doc opt, io
74
+ opt.to_doc io
75
+ end
76
+ end
77
+ end
data/lib/pvn/config.rb ADDED
@@ -0,0 +1,65 @@
1
+ #!/usr/bin/ruby -w
2
+ # -*- ruby -*-
3
+
4
+ require 'rubygems'
5
+ require 'riel'
6
+ require 'singleton'
7
+
8
+ module PVN
9
+ class Configuration
10
+ def initialize
11
+ @@instance = self
12
+ @values = Hash.new { |h, k| h[k] = Array.new }
13
+ end
14
+
15
+ def config &blk
16
+ blk.call self
17
+ end
18
+
19
+ def self.config &blk
20
+ @@instance.config(&blk)
21
+ end
22
+
23
+ def self.read
24
+ @@instance ||= begin
25
+ cfg = self.new
26
+ pvndir = ENV['HOME'] + '/.pvn'
27
+ cfgfile = pvndir + '/config'
28
+
29
+ begin
30
+ require cfgfile
31
+ rescue LoadError => e
32
+ # no configuration
33
+ end
34
+ cfg
35
+ end
36
+ end
37
+
38
+ def value name, field
39
+ @values[name][field]
40
+ end
41
+
42
+ def section name
43
+ @values[name]
44
+ end
45
+
46
+ def method_missing meth, *args, &blk
47
+ eqre = Regexp.new('^(\w+)=')
48
+ # puts "method missing: #{meth}"
49
+ if md = eqre.match(meth.to_s)
50
+ name = md[1]
51
+ @values[@current] << [ name.to_s, *args ]
52
+ # puts "@values: #{@values}"
53
+ else
54
+ @current = meth.to_s
55
+ yield self
56
+ @current = nil
57
+ end
58
+ end
59
+ end
60
+ end
61
+
62
+
63
+ if __FILE__ == $0
64
+ cfg = PVN::Configuration.read
65
+ end
@@ -0,0 +1,40 @@
1
+ #!/usr/bin/ruby -w
2
+ # -*- ruby -*-
3
+
4
+ require 'system/command'
5
+ # require 'pvn/diff'
6
+
7
+ module PVN
8
+ class DescribeCommand < Command
9
+ COMMAND = "describe"
10
+
11
+ self.doc do |doc|
12
+ doc.subcommands = [ COMMAND, 'desc' ]
13
+ doc.description = "Describes the changes of one or more revisions."
14
+ doc.usage = "[OPTIONS] FILE..."
15
+ doc.summary = [ " Prints the log message and the files changed for the given",
16
+ " revisions." ]
17
+ doc.examples << [ "pvn describe -1 foo.rb", "Prints the summary for the most recent revision of foo.rb." ]
18
+ end
19
+
20
+ # has_option :limit, '-l', "the number of log entries", DEFAULT_LIMIT, :negate => [ %r{^--no-?limit} ]
21
+ has_revision_option :multiple => true
22
+
23
+ def initialize args = Hash.new
24
+ info "args: #{args}".on_blue
25
+ super
26
+ end
27
+
28
+ def run args
29
+ info "args: #{args}".on_yellow
30
+ revisions = find_option(:revision).value
31
+
32
+ info "revisions: #{revisions}".yellow
33
+
34
+ revisions.each do |rev|
35
+ info "svn log -r #{rev}"
36
+ info "svn diff --summarize -c #{rev}"
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,49 @@
1
+ #!/usr/bin/ruby -w
2
+ # -*- ruby -*-
3
+
4
+ require 'pvn/config'
5
+ require 'pvn/svn/command/svncmd'
6
+ require 'pvn/diff/diffopts'
7
+
8
+ module PVN
9
+ class DiffCommand < SVNCommand
10
+ COMMAND = "diff"
11
+
12
+ attr_reader :options
13
+
14
+ self.doc do |doc|
15
+ doc.subcommands = [ COMMAND ]
16
+ doc.description = "Displays differences between revisions."
17
+ doc.usage = "[OPTIONS] FILE..."
18
+ doc.summary = [ "Compare two revisions, filtering through external programs.",
19
+ "For each file compared, the file extension is used to find",
20
+ "a diff program." ]
21
+ doc.options.concat DiffOptionSet.new.options
22
+ doc.examples << [ "pvn diff foo.rb", "Compares foo.rb against the last updated version." ]
23
+ doc.examples << [ "pvn diff -3 StringExt.java", "Compares StringExt.java at change (HEAD - 3), using a Java-specific program such as DiffJ." ]
24
+ doc.examples << [ "pvn diff -r +4 -w", "Compares the 4th revision against the working copy, ignoring whitespace." ]
25
+ end
26
+
27
+ def initialize args = Hash.new
28
+ @options = DiffOptionSet.new
29
+ debug "args: #{args.inspect}".yellow
30
+
31
+ super
32
+ end
33
+
34
+ def use_cache?
35
+ super && !against_head?
36
+ end
37
+
38
+ def against_head?
39
+ @options.change.value.nil? && @options.revision.head?
40
+ end
41
+
42
+ # @todo implement
43
+ if true
44
+ self.options do |opts|
45
+ # opts.add :diffcmd
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,67 @@
1
+ #!/usr/bin/ruby -w
2
+ # -*- ruby -*-
3
+
4
+ require 'pathname'
5
+ require 'pvn/config'
6
+
7
+ module PVN
8
+ # the app for svn --diff-cmd
9
+ class Differ
10
+ include Loggable
11
+
12
+ def initialize args
13
+ fromlabel = args[2]
14
+ tolabel = args[4]
15
+
16
+ fromname, fromrev = fromlabel.split("\t")
17
+ toname, torev = tolabel.split("\t")
18
+
19
+ fromfile = args[-2]
20
+ tofile = args[-1]
21
+
22
+ diffcmd = diff_command_by_ext fromname
23
+ info "diffcmd: #{diffcmd}"
24
+
25
+ if diffcmd
26
+ workingcmd = diffcmd.dup
27
+
28
+ [ fromlabel, tolabel, fromfile, tofile ].each_with_index do |str, idx|
29
+ workingcmd.gsub! Regexp.new('\{' + idx.to_s + '\}'), str
30
+ end
31
+
32
+ run_command workingcmd
33
+ else
34
+ run_diff_default fromlabel, tolabel, fromfile, tofile
35
+ end
36
+ end
37
+
38
+ def diff_command_by_ext fname
39
+ extname = Pathname.new(fname).extname
40
+ return nil if extname.empty?
41
+
42
+ ext = extname[1 .. -1]
43
+
44
+ cfg = PVN::Configuration.read
45
+
46
+ diffcfg = cfg.section "diff"
47
+ return nil unless diffcfg
48
+
49
+ diff_for_ext = diffcfg.assoc(ext)
50
+ diff_for_ext && diff_for_ext[1]
51
+ end
52
+
53
+ def run_diff_default fromfname, tofname, fromfile, tofile
54
+ cmd = "diff -u --label \"#{fromfname}\" --label \"#{tofname}\" #{fromfile} #{tofile}"
55
+ run_command cmd
56
+ end
57
+
58
+ def run_command cmd
59
+ info "cmd: #{cmd}".red
60
+ IO.popen(cmd) do |io|
61
+ io.each do |line|
62
+ puts line
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,58 @@
1
+ #!/usr/bin/ruby -w
2
+ # -*- ruby -*-
3
+
4
+ require 'synoption/set'
5
+ require 'pvn/subcommands/revision/revision_option'
6
+
7
+ module PVN
8
+ thisfile = Pathname.new __FILE__
9
+ PVNDIFF_CMD = (thisfile.parent.parent.parent.parent + "bin/pvndiff").expand_path
10
+
11
+ POS_NEG_NUMERIC_RE = Regexp.new('^[\-\+]?\d+$')
12
+
13
+ # "pvn diff -3" == "pvn diff -c -3", not "pvn diff -r -3", because
14
+ # we diff for the change, not from that revision to head.
15
+
16
+ class DiffRevisionOption < RevisionOption
17
+ def head?
18
+ value.nil? || value == 'HEAD'
19
+ end
20
+ end
21
+
22
+ class DiffChangeOption < Option
23
+ def initialize chgargs = Hash.new
24
+ chgargs[:setter] = :revision_from_args
25
+ chgargs[:regexp] = POS_NEG_NUMERIC_RE
26
+
27
+ super :change, '-c', "change", chgargs
28
+ end
29
+ end
30
+
31
+ class DiffWhitespaceOption < Option
32
+ def initialize wsargs = Hash.new
33
+ super :whitespace, '-W', "ignore all whitespace", wsargs
34
+ end
35
+
36
+ def to_command_line
37
+ if value
38
+ %w{ -x -w -x -b -x --ignore-eol-style }
39
+ end
40
+ end
41
+ end
42
+
43
+ class DiffOptionSet < OptionSet
44
+ attr_reader :change
45
+ attr_reader :revision
46
+
47
+ def initialize
48
+ super
49
+
50
+ # diffcmd is old/new option style (non-subclass of Option)
51
+ diffcmd = PVNDIFF_CMD.exist? && PVNDIFF_CMD
52
+ @diffcmdopt = add Option.new :diffcmd, "--diff-cmd", "the program to run diff through", diffcmd, :negate => [ %r{^--no-?diff-?cmd} ]
53
+ @change = add DiffChangeOption.new
54
+ @revision = add DiffRevisionOption.new
55
+ @whitespace = add DiffWhitespaceOption.new
56
+ end
57
+ end
58
+ end
data/lib/pvn/doc.rb ADDED
@@ -0,0 +1,34 @@
1
+ #!/usr/bin/ruby -w
2
+ # -*- ruby -*-
3
+
4
+ require 'rubygems'
5
+ require 'riel'
6
+ require 'pvn/documenter'
7
+
8
+ # Log.level = Log::DEBUG
9
+
10
+ module PVN
11
+ module Doc
12
+ include Loggable
13
+
14
+ def self.included base
15
+ base.extend ClassMethods
16
+ end
17
+
18
+ module ClassMethods
19
+ [ :subcommands, :description, :usage, :summary, :examples ].each do |name|
20
+ define_method name do |val|
21
+ self.instance_eval do
22
+ @doc ||= Documenter.new
23
+ meth = (name.to_s + '=').to_sym
24
+ @doc.send meth, val
25
+ end
26
+ end
27
+ end
28
+
29
+ def to_doc io = $stdout
30
+ self.instance_eval { @doc.to_doc io }
31
+ end
32
+ end
33
+ end
34
+ end