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.
- data/README.markdown +38 -0
- data/bin/pvn +12 -0
- data/bin/pvndiff +10 -0
- data/lib/pvn/app.rb +144 -0
- data/lib/pvn/base/textlines.rb +35 -0
- data/lib/pvn/base/util.rb +14 -0
- data/lib/pvn/cmddoc.rb +77 -0
- data/lib/pvn/config.rb +65 -0
- data/lib/pvn/describe.rb +40 -0
- data/lib/pvn/diff/diffcmd.rb +49 -0
- data/lib/pvn/diff/differ.rb +67 -0
- data/lib/pvn/diff/diffopts.rb +58 -0
- data/lib/pvn/doc.rb +34 -0
- data/lib/pvn/io/element.rb +113 -0
- data/lib/pvn/io/fselement.rb +22 -0
- data/lib/pvn/log/formatter/color_formatter.rb +29 -0
- data/lib/pvn/log/formatter/entries_formatter.rb +33 -0
- data/lib/pvn/log/formatter/entry_formatter.rb +57 -0
- data/lib/pvn/log/formatter/log_formatter.rb +59 -0
- data/lib/pvn/log/formatter/message_formatter.rb +19 -0
- data/lib/pvn/log/formatter/path_formatter.rb +41 -0
- data/lib/pvn/log/formatter/summary_formatter.rb +49 -0
- data/lib/pvn/log/logcmd.rb +136 -0
- data/lib/pvn/log/logentry.rb +116 -0
- data/lib/pvn/log/logfactory.rb +101 -0
- data/lib/pvn/log/logoptions.rb +43 -0
- data/lib/pvn/pct/linecount.rb +33 -0
- data/lib/pvn/pct/pctcmd.rb +204 -0
- data/lib/pvn/pct/statcmd.rb +13 -0
- data/lib/pvn/revision/entry.rb +94 -0
- data/lib/pvn/revision.rb +119 -0
- data/lib/pvn/subcommands/base/clargs.rb +53 -0
- data/lib/pvn/subcommands/base/command.rb +60 -0
- data/lib/pvn/subcommands/base/doc.rb +94 -0
- data/lib/pvn/subcommands/base/options.rb +22 -0
- data/lib/pvn/subcommands/log/command.rb +70 -0
- data/lib/pvn/subcommands/log/options.rb +43 -0
- data/lib/pvn/subcommands/pct/clargs.rb +33 -0
- data/lib/pvn/subcommands/pct/command.rb +57 -0
- data/lib/pvn/subcommands/revision/multiple_revisions_option.rb +43 -0
- data/lib/pvn/subcommands/revision/revision_option.rb +74 -0
- data/lib/pvn/subcommands/revision/revision_regexp_option.rb +39 -0
- data/lib/pvn/svn/command/svncmd.rb +39 -0
- data/lib/pvn/svn/environment.rb +23 -0
- data/lib/pvn/svn/svnelement.rb +89 -0
- data/lib/pvn/svn/svninfo.rb +42 -0
- data/lib/pvn/svn/svnroot.rb +29 -0
- data/lib/pvn/upp/uppcmd.rb +112 -0
- data/lib/pvn/wherecmd.rb +55 -0
- data/lib/pvn.rb +8 -0
- data/lib/svnx/command.rb +60 -0
- data/lib/svnx/entry.rb +34 -0
- data/lib/svnx/info/command.rb +21 -0
- data/lib/svnx/info/entries.rb +27 -0
- data/lib/svnx/info/entry.rb +34 -0
- data/lib/svnx/log/command.rb +93 -0
- data/lib/svnx/log/entries.rb +57 -0
- data/lib/svnx/log/entry.rb +54 -0
- data/lib/svnx/status/command.rb +21 -0
- data/lib/svnx/status/entries.rb +22 -0
- data/lib/svnx/status/entry.rb +33 -0
- data/lib/synoption/base_option.rb +149 -0
- data/lib/synoption/boolean_option.rb +21 -0
- data/lib/synoption/doc.rb +81 -0
- data/lib/synoption/fixnum_option.rb +13 -0
- data/lib/synoption/match.rb +47 -0
- data/lib/synoption/option.rb +10 -0
- data/lib/synoption/optionable.rb +66 -0
- data/lib/synoption/set.rb +114 -0
- data/lib/system/cachecmd.rb +65 -0
- data/lib/system/cmdexec.rb +13 -0
- data/lib/system/cmdline.rb +70 -0
- data/lib/system/command/arg.rb +12 -0
- data/lib/system/command/cachefile.rb +39 -0
- data/lib/system/command/caching.rb +36 -0
- data/lib/system/command/line.rb +47 -0
- data/lib/system/command.rb +72 -0
- data/test/integration/svnx/log/test.rb +43 -0
- data/test/unit/pvn/app_test.rb +22 -0
- data/test/unit/pvn/io/element/log/log_test.rb +35 -0
- data/test/unit/pvn/log/formatter/entry_formatter_test.rb +90 -0
- data/test/unit/pvn/revision/entry_test.rb +123 -0
- data/test/unit/pvn/subcommands/log/command_test.rb +22 -0
- data/test/unit/pvn/subcommands/log/options_test.rb +85 -0
- data/test/unit/pvn/subcommands/revision/multiple_revisions_option_test.rb +67 -0
- data/test/unit/pvn/subcommands/revision/revision_option_test.rb +57 -0
- data/test/unit/pvn/subcommands/revision/revision_regexp_option_test.rb +69 -0
- data/test/unit/svnx/info/entry_test.rb +52 -0
- data/test/unit/svnx/log/cmargs_test.rb +22 -0
- data/test/unit/svnx/log/entries_test.rb +73 -0
- data/test/unit/svnx/log/entry_test.rb +21 -0
- data/test/unit/svnx/status/entry_test.rb +39 -0
- data/test/unit/synoption/base_option_test.rb +182 -0
- data/test/unit/synoption/match_test.rb +61 -0
- data/test/unit/synoption/option_test.rb +15 -0
- data/test/unit/synoption/set_test.rb +37 -0
- data/test/unit/system/command/caching_test.rb +97 -0
- data/test/unit/system/command/line_test.rb +33 -0
- 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
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
|
data/lib/pvn/describe.rb
ADDED
@@ -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
|