pvn 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
@@ -0,0 +1,113 @@
|
|
1
|
+
#!/usr/bin/ruby -w
|
2
|
+
# -*- ruby -*-
|
3
|
+
|
4
|
+
require 'rubygems'
|
5
|
+
require 'riel'
|
6
|
+
require 'pvn/base/util'
|
7
|
+
|
8
|
+
require 'svnx/log/command'
|
9
|
+
require 'svnx/log/entries'
|
10
|
+
|
11
|
+
require 'svnx/status/command'
|
12
|
+
require 'svnx/status/entries'
|
13
|
+
|
14
|
+
require 'svnx/info/command'
|
15
|
+
require 'svnx/info/entries'
|
16
|
+
|
17
|
+
require 'pvn/io/fselement'
|
18
|
+
|
19
|
+
module PVN; module IO; end; end
|
20
|
+
|
21
|
+
module PVN::IO
|
22
|
+
# An element unites an svn element and a file/directory (at least one of
|
23
|
+
# which should exist).
|
24
|
+
|
25
|
+
class Element
|
26
|
+
include Loggable
|
27
|
+
|
28
|
+
attr_reader :svn
|
29
|
+
attr_reader :local
|
30
|
+
|
31
|
+
def initialize args = Hash.new
|
32
|
+
info "args: #{args}"
|
33
|
+
|
34
|
+
svnurl = args[:svnurl]
|
35
|
+
fname = args[:filename] || args[:file] # legacy
|
36
|
+
# $$$ todo: map svnurl to SVNElement, and fname to FSElement
|
37
|
+
|
38
|
+
@svn = args[:svn] || (args[:file] && SVNElement.new(:filename => args[:file]))
|
39
|
+
@local = PVN::FSElement.new args[:local] || args[:file]
|
40
|
+
|
41
|
+
info "local: #{@local}"
|
42
|
+
end
|
43
|
+
|
44
|
+
def exist?
|
45
|
+
@local && @local.exist?
|
46
|
+
end
|
47
|
+
|
48
|
+
def directory?
|
49
|
+
if exist?
|
50
|
+
@local.directory?
|
51
|
+
else
|
52
|
+
# look it up with svn info
|
53
|
+
false
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def file?
|
58
|
+
if exist?
|
59
|
+
@local.file?
|
60
|
+
else
|
61
|
+
raise "need this"
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def svninfo
|
66
|
+
end
|
67
|
+
|
68
|
+
# returns log entries
|
69
|
+
def log cmdargs = SVNx::LogCommandArgs.new
|
70
|
+
# $$$ todo: this should be either @local if set, otherwise @svn (url)
|
71
|
+
# cmdargs.path = @local
|
72
|
+
cmd = SVNx::LogCommand.new cmdargs
|
73
|
+
SVNx::Log::Entries.new :xmllines => cmd.execute
|
74
|
+
end
|
75
|
+
|
76
|
+
# returns :added, :deleted, "modified"
|
77
|
+
def status
|
78
|
+
cmdargs = SVNx::StatusCommandArgs.new :path => @local
|
79
|
+
cmd = SVNx::StatusCommand.new :cmdargs => cmdargs
|
80
|
+
xml = cmd.execute.join ''
|
81
|
+
entries = SVNx::Status::Entries.new :xml => SVNx::Status::XMLEntries.new(xml)
|
82
|
+
entry = entries[0]
|
83
|
+
entry.status
|
84
|
+
end
|
85
|
+
|
86
|
+
# def to_command subcmd, revcl, *args
|
87
|
+
# cmd = "svn #{subcmd}"
|
88
|
+
# info "cmd: #{cmd}".on_blue
|
89
|
+
# info "args: #{args}".on_blue
|
90
|
+
# args = args.flatten
|
91
|
+
|
92
|
+
# # revcl is [ -r, 3484 ]
|
93
|
+
# if revcl
|
94
|
+
# cmd << " " << revcl.join(" ")
|
95
|
+
# end
|
96
|
+
# cmd << " " << Util::quote_list(args)
|
97
|
+
# info "cmd: #{cmd}".on_blue
|
98
|
+
# cmd
|
99
|
+
# end
|
100
|
+
|
101
|
+
# def line_counts
|
102
|
+
# [ @svnelement && @svnelement.line_count, @fselement && @fselement.line_count ]
|
103
|
+
# end
|
104
|
+
|
105
|
+
def <=> other
|
106
|
+
@svn <=> other.svn
|
107
|
+
end
|
108
|
+
|
109
|
+
def to_s
|
110
|
+
"svn => " + @svn.to_s + "; local => " + @local.to_s
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
#!/usr/bin/ruby -w
|
2
|
+
# -*- ruby -*-
|
3
|
+
|
4
|
+
require 'rubygems'
|
5
|
+
require 'riel'
|
6
|
+
|
7
|
+
module PVN
|
8
|
+
# A filesystem element (directory or file).
|
9
|
+
class FSElement < Pathname
|
10
|
+
include Loggable
|
11
|
+
attr_reader :name
|
12
|
+
|
13
|
+
def initialize name
|
14
|
+
@name = name
|
15
|
+
super
|
16
|
+
end
|
17
|
+
|
18
|
+
def line_count
|
19
|
+
readlines.size
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
#!/usr/bin/ruby -w
|
2
|
+
# -*- ruby -*-
|
3
|
+
|
4
|
+
require 'rubygems'
|
5
|
+
require 'riel/log'
|
6
|
+
|
7
|
+
module PVN
|
8
|
+
class ColorFormatter
|
9
|
+
include Loggable
|
10
|
+
|
11
|
+
def pad what, field
|
12
|
+
nspaces = [ width(field) - what.length, 1 ].max
|
13
|
+
" " * nspaces
|
14
|
+
end
|
15
|
+
|
16
|
+
def colorize what, field
|
17
|
+
colors = colors field
|
18
|
+
return what if colors.nil? || colors.empty?
|
19
|
+
colors.each do |col|
|
20
|
+
what = what.send col
|
21
|
+
end
|
22
|
+
what
|
23
|
+
end
|
24
|
+
|
25
|
+
def add_field value, field
|
26
|
+
colorize(value, field) + pad(value, field)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
#!/usr/bin/ruby -w
|
2
|
+
# -*- ruby -*-
|
3
|
+
|
4
|
+
require 'pvn/log/formatter/log_formatter'
|
5
|
+
require 'pvn/log/formatter/entry_formatter'
|
6
|
+
|
7
|
+
module PVN; module Log; end; end
|
8
|
+
|
9
|
+
module PVN::Log
|
10
|
+
class EntriesFormatter < Formatter
|
11
|
+
attr_reader :from_head
|
12
|
+
attr_reader :from_tail
|
13
|
+
|
14
|
+
def initialize use_color, entries, from_head, from_tail
|
15
|
+
super use_color
|
16
|
+
@entries = entries
|
17
|
+
@from_head = from_head
|
18
|
+
@from_tail = from_tail
|
19
|
+
end
|
20
|
+
|
21
|
+
def format
|
22
|
+
lines = Array.new
|
23
|
+
total = @entries.size
|
24
|
+
@entries.each_with_index do |entry, idx|
|
25
|
+
ef = EntryFormatter.new use_colors, entry, idx, from_head, from_tail, total
|
26
|
+
lines.concat ef.format
|
27
|
+
|
28
|
+
lines << '-' * 55
|
29
|
+
end
|
30
|
+
lines
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
#!/usr/bin/ruby -w
|
2
|
+
# -*- ruby -*-
|
3
|
+
|
4
|
+
require 'pvn/log/formatter/log_formatter'
|
5
|
+
require 'pvn/log/formatter/summary_formatter'
|
6
|
+
require 'pvn/log/formatter/message_formatter'
|
7
|
+
require 'pvn/log/formatter/path_formatter'
|
8
|
+
|
9
|
+
module PVN; module Log; end; end
|
10
|
+
|
11
|
+
module PVN::Log
|
12
|
+
class EntryFormatter < Formatter
|
13
|
+
attr_reader :entry
|
14
|
+
attr_reader :idx
|
15
|
+
attr_reader :from_head
|
16
|
+
attr_reader :from_tail
|
17
|
+
attr_reader :total
|
18
|
+
|
19
|
+
def initialize use_colors, entry, idx, from_head, from_tail, total
|
20
|
+
super use_colors
|
21
|
+
@entry = entry
|
22
|
+
@idx = idx
|
23
|
+
@from_head = from_head
|
24
|
+
@from_tail = from_tail
|
25
|
+
@total = total
|
26
|
+
end
|
27
|
+
|
28
|
+
def format
|
29
|
+
if false
|
30
|
+
info "@entry.revision: #{@entry.revision}"
|
31
|
+
info "@entry.author : #{@entry.author}"
|
32
|
+
info "@entry.date : #{@entry.date}"
|
33
|
+
info "@entry.message : #{@entry.message}"
|
34
|
+
@entry.paths.each do |path|
|
35
|
+
info " path.kind : #{path.kind}"
|
36
|
+
info " path.action: #{path.action}"
|
37
|
+
info " path.name : #{path.name}"
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
lines = Array.new
|
42
|
+
|
43
|
+
sf = SummaryFormatter.new use_colors, entry, idx, from_head, from_tail, total
|
44
|
+
lines << sf.format
|
45
|
+
lines << ""
|
46
|
+
|
47
|
+
mf = MessageFormatter.new use_colors, entry.message
|
48
|
+
lines << mf.format
|
49
|
+
lines << ""
|
50
|
+
|
51
|
+
pf = PathFormatter.new use_colors, entry.paths
|
52
|
+
lines.concat pf.format
|
53
|
+
|
54
|
+
lines
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
#!/usr/bin/ruby -w
|
2
|
+
# -*- ruby -*-
|
3
|
+
|
4
|
+
require 'svnx/log/entry'
|
5
|
+
require 'pvn/log/formatter/color_formatter'
|
6
|
+
|
7
|
+
module PVN; module Log; end; end
|
8
|
+
|
9
|
+
module PVN::Log
|
10
|
+
# a format for log entries
|
11
|
+
class Formatter < PVN::ColorFormatter
|
12
|
+
|
13
|
+
WIDTHS = {
|
14
|
+
:revision => 10,
|
15
|
+
:neg_revision => 5,
|
16
|
+
:pos_revision => 5,
|
17
|
+
:author => 25
|
18
|
+
}
|
19
|
+
|
20
|
+
COLORS = {
|
21
|
+
:revision => [ :bold ],
|
22
|
+
:neg_revision => [ :bold ],
|
23
|
+
:pos_revision => [ :bold ],
|
24
|
+
:author => [ :bold, :cyan ],
|
25
|
+
:date => [ :bold, :magenta ],
|
26
|
+
|
27
|
+
:added => [ :green ],
|
28
|
+
:modified => [ :yellow ],
|
29
|
+
:deleted => [ :red ],
|
30
|
+
:renamed => [ :magenta ],
|
31
|
+
|
32
|
+
:dir => [ :bold ],
|
33
|
+
}
|
34
|
+
|
35
|
+
attr_reader :use_colors
|
36
|
+
|
37
|
+
def initialize use_colors
|
38
|
+
@use_colors = use_colors
|
39
|
+
# should also turn this off if not on a terminal that supports colors ...
|
40
|
+
end
|
41
|
+
|
42
|
+
def write_entries entries, out = $stdout
|
43
|
+
entries.each_with_index do |entry, idx|
|
44
|
+
fmtlines = format entry, idx, entries.size
|
45
|
+
|
46
|
+
out.puts fmtlines
|
47
|
+
out.puts '-' * 55
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def width field
|
52
|
+
WIDTHS[field]
|
53
|
+
end
|
54
|
+
|
55
|
+
def colors field
|
56
|
+
use_colors ? COLORS[field] : nil
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
#!/usr/bin/ruby -w
|
2
|
+
# -*- ruby -*-
|
3
|
+
|
4
|
+
require 'pvn/log/formatter/log_formatter'
|
5
|
+
|
6
|
+
module PVN; module Log; end; end
|
7
|
+
|
8
|
+
module PVN::Log
|
9
|
+
class MessageFormatter < Formatter
|
10
|
+
def initialize use_colors, msg
|
11
|
+
super use_colors
|
12
|
+
@msg = msg
|
13
|
+
end
|
14
|
+
|
15
|
+
def format
|
16
|
+
use_colors ? @msg.white : @msg
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
#!/usr/bin/ruby -w
|
2
|
+
# -*- ruby -*-
|
3
|
+
|
4
|
+
require 'pvn/log/formatter/log_formatter'
|
5
|
+
|
6
|
+
module PVN; module Log; end; end
|
7
|
+
|
8
|
+
module PVN::Log
|
9
|
+
class PathFormatter < Formatter
|
10
|
+
PATH_ACTIONS = {
|
11
|
+
'M' => :modified,
|
12
|
+
'A' => :added,
|
13
|
+
'D' => :deleted,
|
14
|
+
'R' => :renamed
|
15
|
+
}
|
16
|
+
|
17
|
+
def initialize use_colors, paths
|
18
|
+
super use_colors
|
19
|
+
@paths = paths
|
20
|
+
end
|
21
|
+
|
22
|
+
def format
|
23
|
+
lines = Array.new
|
24
|
+
@paths.sort_by { |path| path.name }.each do |path|
|
25
|
+
pstr = " "
|
26
|
+
if field = PATH_ACTIONS[path.action]
|
27
|
+
pstr << colorize(path.name, field)
|
28
|
+
else
|
29
|
+
raise "wtf?: #{path.action}"
|
30
|
+
end
|
31
|
+
|
32
|
+
if path.kind == 'dir'
|
33
|
+
pstr = colorize(pstr, :dir)
|
34
|
+
end
|
35
|
+
|
36
|
+
lines << pstr
|
37
|
+
end
|
38
|
+
lines
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
#!/usr/bin/ruby -w
|
2
|
+
# -*- ruby -*-
|
3
|
+
|
4
|
+
require 'pvn/log/formatter/log_formatter'
|
5
|
+
|
6
|
+
module PVN; module Log; end; end
|
7
|
+
|
8
|
+
module PVN::Log
|
9
|
+
class SummaryFormatter < Formatter
|
10
|
+
attr_reader :entry
|
11
|
+
attr_reader :idx
|
12
|
+
attr_reader :from_head
|
13
|
+
attr_reader :from_tail
|
14
|
+
attr_reader :total
|
15
|
+
|
16
|
+
def initialize use_colors, entry, idx, from_head, from_tail, total
|
17
|
+
super use_colors
|
18
|
+
@entry = entry
|
19
|
+
@idx = idx
|
20
|
+
@from_head = from_head
|
21
|
+
@from_tail = from_tail
|
22
|
+
@total = total
|
23
|
+
end
|
24
|
+
|
25
|
+
def format
|
26
|
+
lines = add_field(entry.revision, :revision)
|
27
|
+
negidx = (-1 - idx).to_s
|
28
|
+
|
29
|
+
if from_head
|
30
|
+
lines << add_field(negidx, :neg_revision)
|
31
|
+
else
|
32
|
+
lines << pad("", :neg_revision)
|
33
|
+
end
|
34
|
+
|
35
|
+
# info "@total: #{total}"
|
36
|
+
|
37
|
+
if from_tail
|
38
|
+
posidx = "+#{total - idx - 1}"
|
39
|
+
lines << add_field(posidx, :pos_revision)
|
40
|
+
else
|
41
|
+
lines << pad("", :pos_revision)
|
42
|
+
end
|
43
|
+
|
44
|
+
lines << add_field(entry.author, :author)
|
45
|
+
lines << colorize(entry.date, :date)
|
46
|
+
lines
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,136 @@
|
|
1
|
+
#!/usr/bin/ruby -w
|
2
|
+
# -*- ruby -*-
|
3
|
+
|
4
|
+
require 'system/command'
|
5
|
+
require 'system/cachecmd'
|
6
|
+
require 'pvn/svn/command/svncmd'
|
7
|
+
require 'pvn/log/logfactory'
|
8
|
+
require 'pvn/log/logoptions'
|
9
|
+
|
10
|
+
module PVN
|
11
|
+
class LogCommand < SVNCommand
|
12
|
+
COMMAND = "log"
|
13
|
+
REVISION_ARG = '-r'
|
14
|
+
|
15
|
+
attr_reader :options
|
16
|
+
|
17
|
+
self.doc do |doc|
|
18
|
+
doc.subcommands = [ COMMAND, 'l' ]
|
19
|
+
doc.description = "Print log messages for the given files."
|
20
|
+
doc.usage = "[OPTIONS] FILE..."
|
21
|
+
doc.summary = [ "Prints the log entries for the given files, with colorized",
|
22
|
+
"output. Unlike 'svn log', which prints all log entries, ",
|
23
|
+
"'pvn log' prints #{DEFAULT_LIMIT} entries by default.",
|
24
|
+
"As with other pvn commands, 'pvn log' accepts relative ",
|
25
|
+
"revisions."
|
26
|
+
]
|
27
|
+
doc.options.concat LogOptionSet.new.options
|
28
|
+
doc.examples << [ "pvn log foo.rb", "Prints the latest #{DEFAULT_LIMIT} log entries for foo.rb." ]
|
29
|
+
doc.examples << [ "pvn log -l 25 foo.rb", "Prints 25 log entries for the file." ]
|
30
|
+
doc.examples << [ "pvn log -3 foo.rb", "Prints the log entry for revision (HEAD - 3)." ]
|
31
|
+
doc.examples << [ "pvn log +3 foo.rb", "Prints the 3rd log entry." ]
|
32
|
+
doc.examples << [ "pvn log -l 10 -F", "Prints the latest 10 entries, unformatted." ]
|
33
|
+
doc.examples << [ "pvn log -r 122 -v", "Prints log entry for revision 122, with the files in that change." ]
|
34
|
+
end
|
35
|
+
|
36
|
+
def initialize args = Hash.new
|
37
|
+
@options = LogOptionSet.new
|
38
|
+
|
39
|
+
debug "args: #{args.inspect}"
|
40
|
+
|
41
|
+
@options.revision.fromdate = args[:fromdate]
|
42
|
+
@options.revision.todate = args[:todate]
|
43
|
+
|
44
|
+
@options.options.each do |opt|
|
45
|
+
info "opt: #{opt}".blue
|
46
|
+
end
|
47
|
+
|
48
|
+
@entries = nil
|
49
|
+
|
50
|
+
super
|
51
|
+
end
|
52
|
+
|
53
|
+
def has_entries?
|
54
|
+
true
|
55
|
+
end
|
56
|
+
|
57
|
+
def use_cache?
|
58
|
+
# use cache unless log is to head.
|
59
|
+
super && !@options.revision.head?
|
60
|
+
end
|
61
|
+
|
62
|
+
def entries
|
63
|
+
@entries ||= begin
|
64
|
+
# of course this assumes that output is in plain text (non-XML)
|
65
|
+
factory = PVN::Log::TextFactory.new output
|
66
|
+
factory.entries
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def revision_of_nth_entry num
|
71
|
+
entry = nth_entry num
|
72
|
+
entry && entry.revision.to_i
|
73
|
+
end
|
74
|
+
|
75
|
+
def nth_entry n
|
76
|
+
entries[-1 * n]
|
77
|
+
end
|
78
|
+
|
79
|
+
def write_entries
|
80
|
+
info "@options: #{@options.inspect}"
|
81
|
+
info "@options.format: #{@options.format.inspect}".yellow
|
82
|
+
|
83
|
+
entries.each do |entry|
|
84
|
+
info "@options.format.value: #{@options.format.value}"
|
85
|
+
entry.write @options.format.value
|
86
|
+
end
|
87
|
+
unless @options.format
|
88
|
+
puts PVN::Log::Entry::BANNER
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
# this may be faster than get_nth_entry
|
93
|
+
def read_from_log_output n_matches
|
94
|
+
loglines = output.reverse
|
95
|
+
|
96
|
+
entries = entries
|
97
|
+
entry = entries[-1 * n_matches]
|
98
|
+
|
99
|
+
if true
|
100
|
+
return entry && entry.revision.to_i
|
101
|
+
end
|
102
|
+
|
103
|
+
loglines.each do |line|
|
104
|
+
next unless md = SVN_LOG_SUMMARY_LINE_RE.match(line)
|
105
|
+
|
106
|
+
info "md: #{md}".yellow
|
107
|
+
|
108
|
+
n_matches -= 1
|
109
|
+
if n_matches == 0
|
110
|
+
return md[1].to_i
|
111
|
+
end
|
112
|
+
end
|
113
|
+
nil
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
module PVN::Log
|
119
|
+
class Command < CachableCommand
|
120
|
+
def initialize args
|
121
|
+
command = %w{ svn log }
|
122
|
+
|
123
|
+
# todo: handle revision conversion:
|
124
|
+
fromrev = args[:fromrev]
|
125
|
+
torev = args[:torev]
|
126
|
+
|
127
|
+
if fromrev && torev
|
128
|
+
command << "-r" << "#{fromrev}:#{torev}"
|
129
|
+
elsif args[:fromdate] && args[:todate]
|
130
|
+
command << "-r" << "\{#{fromdate}\}:\{#{todate}\}"
|
131
|
+
end
|
132
|
+
debug "command: #{command}".on_red
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
@@ -0,0 +1,116 @@
|
|
1
|
+
#!/usr/bin/ruby -w
|
2
|
+
# -*- ruby -*-
|
3
|
+
|
4
|
+
require 'rubygems'
|
5
|
+
require 'riel'
|
6
|
+
require 'pvn/config'
|
7
|
+
|
8
|
+
module PVN; module Log; end; end
|
9
|
+
|
10
|
+
module PVN::Log
|
11
|
+
class Entry
|
12
|
+
include Loggable
|
13
|
+
|
14
|
+
FIELDS = [ :revision,
|
15
|
+
:user,
|
16
|
+
:date,
|
17
|
+
:time,
|
18
|
+
:tz,
|
19
|
+
:dtg,
|
20
|
+
:nlines,
|
21
|
+
:files,
|
22
|
+
:comment ]
|
23
|
+
|
24
|
+
FIELDS.each do |field|
|
25
|
+
attr_reader field
|
26
|
+
end
|
27
|
+
|
28
|
+
WRITE_FORMAT_DEFAULT = ('#{revision.yellow}\t#{user.green}\t#{date} #{time}\n' +
|
29
|
+
'#{list(comment)}#{cr(files)}' +
|
30
|
+
'#{list(files, :blue, :on_yellow)}\n')
|
31
|
+
|
32
|
+
WRITE_SUMMARY_LINE = 'r#{revision} | #{user} | #{date} #{time} #{tz} (#{dtg}) | #{nlines} #{nlines.to_i == 1 ? "line" : "lines"}\n'
|
33
|
+
|
34
|
+
WRITE_UNFORMATTED_VERBOSE = (WRITE_SUMMARY_LINE +
|
35
|
+
'Changed Paths:\n' +
|
36
|
+
'#{list(files)}\n' +
|
37
|
+
'#{plainlist(comment)}')
|
38
|
+
|
39
|
+
WRITE_UNFORMATTED_TERSE = (WRITE_SUMMARY_LINE + '\n' +
|
40
|
+
'#{plainlist(comment)}')
|
41
|
+
|
42
|
+
BANNER = '-' * 72
|
43
|
+
|
44
|
+
def set_from_args name, args
|
45
|
+
self.instance_variable_set '@' + name.to_s, args[name]
|
46
|
+
end
|
47
|
+
|
48
|
+
# Reads a log entry from the text, starting at the first line at or after
|
49
|
+
# lidx, matching the svn log separator line. Returns [ entry, new_index ],
|
50
|
+
# where new_index is the updated index into the lines. Returns nil if the
|
51
|
+
# text does not match the expected plain text format.
|
52
|
+
def self.create_from_text lines, lidx = 0
|
53
|
+
return TextOutputReader.create_from_text lines, lidx
|
54
|
+
end
|
55
|
+
|
56
|
+
def initialize args = Hash.new
|
57
|
+
FIELDS.each do |field|
|
58
|
+
set_from_args field, args
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def cr ary
|
63
|
+
ary && !ary.empty? ? "\n" : ''
|
64
|
+
end
|
65
|
+
|
66
|
+
def list lines, *colors
|
67
|
+
return '' unless lines
|
68
|
+
|
69
|
+
lines.collect do |line|
|
70
|
+
ln = line.chomp
|
71
|
+
colors.each do |color|
|
72
|
+
ln = ln.send(color)
|
73
|
+
end
|
74
|
+
" " + ln + "\n"
|
75
|
+
end.join('')
|
76
|
+
end
|
77
|
+
|
78
|
+
def plainlist lines
|
79
|
+
return '' unless lines
|
80
|
+
|
81
|
+
# ensure that each has a newline
|
82
|
+
lines.collect do |line|
|
83
|
+
line.chomp + "\n"
|
84
|
+
end.join('')
|
85
|
+
end
|
86
|
+
|
87
|
+
def write formatted
|
88
|
+
# ------------------------------------------------------------------------
|
89
|
+
# r1907 | hielke.hoeve@gmail.com | 2011-11-14 05:50:38 -0500 (Mon, 14 Nov 2011) | 1 line
|
90
|
+
#
|
91
|
+
# back to dev
|
92
|
+
|
93
|
+
if formatted
|
94
|
+
cfg = PVN::Configuration.read
|
95
|
+
|
96
|
+
logcfg = cfg.section "log"
|
97
|
+
info "logcfg: #{logcfg}"
|
98
|
+
format = logcfg && logcfg.assoc('format') && logcfg.assoc('format')[1]
|
99
|
+
info "format: #{format}"
|
100
|
+
|
101
|
+
format ||= WRITE_FORMAT_DEFAULT
|
102
|
+
|
103
|
+
# @todo allow reformatting of date and time
|
104
|
+
# format = WRITE_FORMAT_DEFAULT
|
105
|
+
msg = eval('"' + format + '"')
|
106
|
+
print msg
|
107
|
+
else
|
108
|
+
puts BANNER
|
109
|
+
|
110
|
+
fmt = files ? WRITE_UNFORMATTED_VERBOSE : WRITE_UNFORMATTED_TERSE
|
111
|
+
|
112
|
+
puts eval('"' + fmt + '"')
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|