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
@@ -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
|