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,33 @@
|
|
1
|
+
#!/usr/bin/ruby -w
|
2
|
+
# -*- ruby -*-
|
3
|
+
|
4
|
+
require 'svnx/entry'
|
5
|
+
|
6
|
+
module SVNx; module Status; end; end
|
7
|
+
|
8
|
+
module SVNx::Status
|
9
|
+
class Entry < SVNx::Entry
|
10
|
+
|
11
|
+
attr_reader :status
|
12
|
+
attr_reader :path
|
13
|
+
|
14
|
+
def initialize args = Hash.new
|
15
|
+
if xmllines = args[:xmllines]
|
16
|
+
doc = REXML::Document.new xmllines
|
17
|
+
stelmt = doc.elements['status']
|
18
|
+
tgt = stelmt.elements['target']
|
19
|
+
|
20
|
+
set_attr_var tgt, 'path'
|
21
|
+
|
22
|
+
if entry = tgt.elements['entry']
|
23
|
+
wcstatus = entry.elements['wc-status']
|
24
|
+
@status = wcstatus.attributes['item']
|
25
|
+
else
|
26
|
+
@status = "unchanged"
|
27
|
+
end
|
28
|
+
else
|
29
|
+
raise "must be initialized with xmllines"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,149 @@
|
|
1
|
+
#!/usr/bin/ruby -w
|
2
|
+
# -*- ruby -*-
|
3
|
+
|
4
|
+
require 'rubygems'
|
5
|
+
require 'riel'
|
6
|
+
require 'synoption/doc'
|
7
|
+
require 'synoption/match'
|
8
|
+
|
9
|
+
module PVN
|
10
|
+
class BaseOption
|
11
|
+
include Loggable
|
12
|
+
|
13
|
+
# for as_cmdline_option:
|
14
|
+
NO_CMDLINE_OPTION = Object.new
|
15
|
+
|
16
|
+
attr_reader :name
|
17
|
+
attr_reader :tag
|
18
|
+
attr_reader :description
|
19
|
+
attr_reader :default
|
20
|
+
|
21
|
+
attr_reader :negate
|
22
|
+
attr_reader :regexp
|
23
|
+
|
24
|
+
def initialize name, tag, description, default, options = Hash.new
|
25
|
+
@name = name
|
26
|
+
@tag = tag
|
27
|
+
@description = description
|
28
|
+
|
29
|
+
@value = @default = default
|
30
|
+
|
31
|
+
@matchers = Hash.new
|
32
|
+
@matchers[:exact] = OptionExactMatch.new @tag, @name
|
33
|
+
|
34
|
+
if @negate = options[:negate]
|
35
|
+
@matchers[:negative] = OptionNegativeMatch.new @negate
|
36
|
+
end
|
37
|
+
|
38
|
+
if @regexp = options[:regexp]
|
39
|
+
@matchers[:regexp] = OptionRegexpMatch.new @regexp
|
40
|
+
end
|
41
|
+
|
42
|
+
if options.include? :as_cmdline_option
|
43
|
+
if options[:as_cmdline_option].nil?
|
44
|
+
@as_cmdline_option = NO_CMDLINE_OPTION
|
45
|
+
else
|
46
|
+
@as_cmdline_option = options[:as_cmdline_option]
|
47
|
+
end
|
48
|
+
else
|
49
|
+
@as_cmdline_option = nil
|
50
|
+
end
|
51
|
+
|
52
|
+
@unsets = options[:unsets]
|
53
|
+
end
|
54
|
+
|
55
|
+
def takes_value?
|
56
|
+
true
|
57
|
+
end
|
58
|
+
|
59
|
+
def to_command_line
|
60
|
+
return nil unless value
|
61
|
+
|
62
|
+
if @as_cmdline_option
|
63
|
+
@as_cmdline_option == NO_CMDLINE_OPTION ? nil : @as_cmdline_option
|
64
|
+
else
|
65
|
+
[ tag, value ]
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def to_s
|
70
|
+
[ @name, @tag ].join(", ")
|
71
|
+
end
|
72
|
+
|
73
|
+
def exact_match? arg
|
74
|
+
@matchers[:exact].match? arg
|
75
|
+
end
|
76
|
+
|
77
|
+
def negative_match? arg
|
78
|
+
@matchers[:negative] and @matchers[:negative].match? arg
|
79
|
+
end
|
80
|
+
|
81
|
+
def regexp_match? arg
|
82
|
+
@matchers[:regexp] and @matchers[:regexp].match? arg
|
83
|
+
end
|
84
|
+
|
85
|
+
def match arg
|
86
|
+
return nil unless arg
|
87
|
+
|
88
|
+
@matchers.each do |type, matcher|
|
89
|
+
if matcher.match? arg
|
90
|
+
return [ type, matcher ]
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
nil
|
95
|
+
end
|
96
|
+
|
97
|
+
def unset
|
98
|
+
@value = nil
|
99
|
+
end
|
100
|
+
|
101
|
+
def set_value val
|
102
|
+
@value = val
|
103
|
+
end
|
104
|
+
|
105
|
+
def value
|
106
|
+
@value
|
107
|
+
end
|
108
|
+
|
109
|
+
def to_doc io
|
110
|
+
doc = Doc.new self
|
111
|
+
doc.to_doc io
|
112
|
+
end
|
113
|
+
|
114
|
+
def next_argument args
|
115
|
+
raise "ERROR: option #{name} expecting following argument" if args.empty?
|
116
|
+
args.shift
|
117
|
+
end
|
118
|
+
|
119
|
+
def process args
|
120
|
+
if @matchers[:exact].match? args[0]
|
121
|
+
args.shift
|
122
|
+
val = takes_value? ? next_argument(args) : true
|
123
|
+
set_value val
|
124
|
+
true
|
125
|
+
elsif @matchers[:negative] && @matchers[:negative].match?(args[0])
|
126
|
+
arg = args.shift
|
127
|
+
set_value false
|
128
|
+
true
|
129
|
+
elsif @matchers[:regexp] && (md = @matchers[:regexp].match?(args[0]))
|
130
|
+
arg = args.shift
|
131
|
+
set_value md[0]
|
132
|
+
true
|
133
|
+
else
|
134
|
+
false
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
def post_process option_set, unprocessed
|
139
|
+
resolve_value option_set, unprocessed
|
140
|
+
|
141
|
+
if @unsets
|
142
|
+
option_set.unset @unsets
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
def resolve_value option_set, unprocessed
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
#!/usr/bin/ruby -w
|
2
|
+
# -*- ruby -*-
|
3
|
+
|
4
|
+
require 'rubygems'
|
5
|
+
require 'riel'
|
6
|
+
require 'synoption/option'
|
7
|
+
|
8
|
+
module PVN
|
9
|
+
# a boolean option maps to a single tag, not a tag and value. For example,
|
10
|
+
# "-v" (verbose) is a boolean option, but "-r 3444" (revision) is a option
|
11
|
+
# with a value.
|
12
|
+
class BooleanOption < Option
|
13
|
+
def takes_value?
|
14
|
+
false
|
15
|
+
end
|
16
|
+
|
17
|
+
def to_command_line
|
18
|
+
super && [ tag ]
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
#!/usr/bin/ruby -w
|
2
|
+
# -*- ruby -*-
|
3
|
+
|
4
|
+
require 'rubygems'
|
5
|
+
require 'riel'
|
6
|
+
|
7
|
+
module PVN
|
8
|
+
# documentation for an option.
|
9
|
+
class Doc
|
10
|
+
include Loggable
|
11
|
+
|
12
|
+
def initialize option
|
13
|
+
@option = option
|
14
|
+
end
|
15
|
+
|
16
|
+
def to_doc_tag
|
17
|
+
tagline = "#{@option.tag} [--#{@option.name}]"
|
18
|
+
if @option.takes_value?
|
19
|
+
tagline << " ARG"
|
20
|
+
end
|
21
|
+
tagline
|
22
|
+
end
|
23
|
+
|
24
|
+
# returns an option regexp as a 'cleaner' string
|
25
|
+
def re_to_string re
|
26
|
+
re.source.gsub(%r{\\d\+?}, 'N').gsub(%r{[\^\?\$\\\(\)]}, '')
|
27
|
+
end
|
28
|
+
|
29
|
+
def to_doc_negate
|
30
|
+
doc = nil
|
31
|
+
@option.negate.each do |neg|
|
32
|
+
str = if neg.kind_of? Regexp
|
33
|
+
str = re_to_string neg
|
34
|
+
else
|
35
|
+
str = neg
|
36
|
+
end
|
37
|
+
|
38
|
+
if doc
|
39
|
+
doc << " [#{str}]"
|
40
|
+
else
|
41
|
+
doc = str
|
42
|
+
end
|
43
|
+
end
|
44
|
+
doc
|
45
|
+
end
|
46
|
+
|
47
|
+
# -g [--use-merge-history] : use/display additional information from merge
|
48
|
+
# 01234567890123456789012345678901234567890123456789012345678901234567890123456789
|
49
|
+
# 0 1 2 3 4 5 6
|
50
|
+
|
51
|
+
def to_doc_line lhs, rhs, sep = ""
|
52
|
+
fmt = " %-24s %1s %s"
|
53
|
+
sprintf fmt, lhs, sep, rhs
|
54
|
+
end
|
55
|
+
|
56
|
+
def to_doc io
|
57
|
+
opttag = @option.tag
|
58
|
+
optdesc = @option.description
|
59
|
+
|
60
|
+
# wrap optdesc?
|
61
|
+
|
62
|
+
@option.description.each_with_index do |descline, idx|
|
63
|
+
lhs = idx == 0 ? to_doc_tag : ""
|
64
|
+
io.puts to_doc_line lhs, descline, idx == 0 ? ":" : ""
|
65
|
+
end
|
66
|
+
|
67
|
+
if defval = @option.default
|
68
|
+
io.puts to_doc_line "", " default: #{defval}"
|
69
|
+
end
|
70
|
+
|
71
|
+
if re = @option.regexp
|
72
|
+
io.puts to_doc_line re_to_string(re), "same as above", ":"
|
73
|
+
end
|
74
|
+
|
75
|
+
if @option.negate
|
76
|
+
lhs = to_doc_negate
|
77
|
+
io.puts to_doc_line lhs, "", ""
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
#!/usr/bin/ruby -w
|
2
|
+
# -*- ruby -*-
|
3
|
+
|
4
|
+
require 'rubygems'
|
5
|
+
require 'riel'
|
6
|
+
|
7
|
+
module PVN
|
8
|
+
class OptionMatch
|
9
|
+
include Loggable
|
10
|
+
|
11
|
+
def match? arg
|
12
|
+
raise "not implemented"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
class OptionExactMatch < OptionMatch
|
17
|
+
def initialize tag, name
|
18
|
+
@tag = tag
|
19
|
+
@name = name
|
20
|
+
end
|
21
|
+
|
22
|
+
def match? arg
|
23
|
+
arg == @tag || arg == '--' + @name.to_s
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
class OptionNegativeMatch < OptionMatch
|
28
|
+
def initialize *negopts
|
29
|
+
# in case this gets passed an array as an element:
|
30
|
+
@negopts = Array.new(negopts).flatten
|
31
|
+
end
|
32
|
+
|
33
|
+
def match? arg
|
34
|
+
arg && @negopts.select { |x| arg.index x }.size > 0
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
class OptionRegexpMatch < OptionMatch
|
39
|
+
def initialize regexp
|
40
|
+
@regexp = regexp
|
41
|
+
end
|
42
|
+
|
43
|
+
def match? arg
|
44
|
+
arg && @regexp.match(arg)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
#!/usr/bin/ruby -w
|
2
|
+
# -*- ruby -*-
|
3
|
+
|
4
|
+
require 'rubygems'
|
5
|
+
require 'riel'
|
6
|
+
require 'synoption/set'
|
7
|
+
require 'synoption/option'
|
8
|
+
require 'pvn/cmddoc'
|
9
|
+
|
10
|
+
module PVN
|
11
|
+
module Optionable
|
12
|
+
include Loggable
|
13
|
+
|
14
|
+
def self.included base
|
15
|
+
base.extend ClassMethods
|
16
|
+
end
|
17
|
+
|
18
|
+
module ClassMethods
|
19
|
+
def has_option optname, tag, desc, args = Hash.new
|
20
|
+
RIEL::Log.debug "self: #{self}"
|
21
|
+
RIEL::Log.debug "optname: #{optname}"
|
22
|
+
|
23
|
+
self.instance_eval do
|
24
|
+
@option_set ||= OptionSet.new
|
25
|
+
opt = Option.new optname, tag, desc, args
|
26
|
+
@option_set.options << opt
|
27
|
+
|
28
|
+
RIEL::Log.debug "self: #{self}"
|
29
|
+
RIEL::Log.debug "opt: #{opt.inspect}"
|
30
|
+
RIEL::Log.debug "@option_set: #{@option_set.inspect}"
|
31
|
+
|
32
|
+
@doc.options << opt
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def find_option optname
|
37
|
+
self.instance_eval do
|
38
|
+
@option_set.find_by_name optname
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def doc
|
43
|
+
@doc ||= CommandDoc.new
|
44
|
+
yield @doc if block_given?
|
45
|
+
@doc
|
46
|
+
end
|
47
|
+
|
48
|
+
def options
|
49
|
+
self.instance_eval do
|
50
|
+
@option_set ||= OptionSet.new
|
51
|
+
RIEL::Log.debug "@option_set: #{@option_set}"
|
52
|
+
yield @option_set if block_given?
|
53
|
+
@option_set
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def to_doc io = $stdout
|
58
|
+
self.instance_eval { @doc.to_doc io }
|
59
|
+
end
|
60
|
+
|
61
|
+
def next_argument_as_integer ca, cmdargs
|
62
|
+
cmdargs.shift.to_i
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,114 @@
|
|
1
|
+
#!/usr/bin/ruby -w
|
2
|
+
# -*- ruby -*-
|
3
|
+
|
4
|
+
require 'rubygems'
|
5
|
+
require 'riel'
|
6
|
+
require 'synoption/option'
|
7
|
+
|
8
|
+
module PVN
|
9
|
+
class OptionSet
|
10
|
+
include Loggable
|
11
|
+
|
12
|
+
# maps from the option set class to the valid options for that class.
|
13
|
+
@@options_for_class = Hash.new { |h, k| h[k] = Array.new }
|
14
|
+
|
15
|
+
attr_reader :unprocessed
|
16
|
+
|
17
|
+
class << self
|
18
|
+
def has_option name, optcls, optargs = Hash.new
|
19
|
+
attr_reader name
|
20
|
+
|
21
|
+
@@options_for_class[self] << { :name => name, :class => optcls, :args => optargs }
|
22
|
+
|
23
|
+
define_method name do
|
24
|
+
instance_eval do
|
25
|
+
meth = name
|
26
|
+
opt = instance_variable_get '@' + name.to_s
|
27
|
+
opt.value
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
attr_reader :options
|
34
|
+
attr_reader :arguments
|
35
|
+
|
36
|
+
def initialize options = Array.new
|
37
|
+
@options = options
|
38
|
+
@arguments = Array.new
|
39
|
+
|
40
|
+
opts = @@options_for_class[self.class]
|
41
|
+
|
42
|
+
opts.each do |option|
|
43
|
+
name = option[:name]
|
44
|
+
cls = option[:class]
|
45
|
+
args = option[:args]
|
46
|
+
opt = cls.new(*args)
|
47
|
+
add opt
|
48
|
+
instance_variable_set '@' + name.to_s, opt
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def inspect
|
53
|
+
@options.collect { |opt| opt.inspect }.join("\n")
|
54
|
+
end
|
55
|
+
|
56
|
+
def find_by_name name
|
57
|
+
@options.find { |opt| opt.name == name }
|
58
|
+
end
|
59
|
+
|
60
|
+
def has_option? name
|
61
|
+
find_by_name name
|
62
|
+
end
|
63
|
+
|
64
|
+
def to_command_line
|
65
|
+
cmdline = Array.new
|
66
|
+
@options.each do |opt|
|
67
|
+
if cl = opt.to_command_line
|
68
|
+
cmdline.concat cl
|
69
|
+
end
|
70
|
+
end
|
71
|
+
cmdline
|
72
|
+
end
|
73
|
+
|
74
|
+
def unset key
|
75
|
+
opt = find_by_name key
|
76
|
+
opt && opt.unset
|
77
|
+
end
|
78
|
+
|
79
|
+
def process args
|
80
|
+
options_processed = Array.new
|
81
|
+
|
82
|
+
@unprocessed = args
|
83
|
+
|
84
|
+
while !@unprocessed.empty?
|
85
|
+
processed = false
|
86
|
+
options.each do |opt|
|
87
|
+
if opt.process @unprocessed
|
88
|
+
processed = true
|
89
|
+
options_processed << opt
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
break unless processed
|
94
|
+
end
|
95
|
+
|
96
|
+
options_processed.each do |opt|
|
97
|
+
opt.post_process self, @unprocessed
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
def << option
|
102
|
+
@options << option
|
103
|
+
end
|
104
|
+
|
105
|
+
def add option
|
106
|
+
@options << option
|
107
|
+
option
|
108
|
+
end
|
109
|
+
|
110
|
+
def as_command_line
|
111
|
+
to_command_line + arguments
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
#!/usr/bin/ruby -w
|
2
|
+
# -*- ruby -*-
|
3
|
+
|
4
|
+
require 'system/command'
|
5
|
+
|
6
|
+
module PVN
|
7
|
+
class CachableCommand < Command
|
8
|
+
TMP_DIR = ENV['PVN_TMP_DIR'] || '/tmp/pvncache'
|
9
|
+
CACHE_DIR = Pathname.new TMP_DIR
|
10
|
+
|
11
|
+
attr_accessor :lines
|
12
|
+
|
13
|
+
def initialize args = Hash.new
|
14
|
+
debug "args: #{args.inspect}"
|
15
|
+
|
16
|
+
@use_cache = args[:use_cache].nil? ? true : args[:use_cache]
|
17
|
+
info "@use_cache: #{@use_cache}".blue
|
18
|
+
|
19
|
+
super
|
20
|
+
end
|
21
|
+
|
22
|
+
def sysexec cmd
|
23
|
+
info "cmd: #{cmd}".on_red
|
24
|
+
if use_cache?
|
25
|
+
info "cmd: #{cmd}".on_green
|
26
|
+
run_cached_command cmd
|
27
|
+
else
|
28
|
+
@output = ::IO::popen(cmd).readlines
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def run args
|
33
|
+
if use_cache?
|
34
|
+
run_cached_command args
|
35
|
+
else
|
36
|
+
super
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def use_cache?
|
41
|
+
@use_cache
|
42
|
+
end
|
43
|
+
|
44
|
+
def get_cache_file cmd
|
45
|
+
pwd = Pathname.pwd.to_s.sub(%r{^/}, '')
|
46
|
+
CACHE_DIR + pwd + cmd.gsub(' ', '')
|
47
|
+
end
|
48
|
+
|
49
|
+
def run_cached_command cmd
|
50
|
+
stack "cmd: #{cmd}".cyan
|
51
|
+
cfile = get_cache_file cmd
|
52
|
+
if cfile.exist?
|
53
|
+
debug "reading from cache file: #{cfile}".cyan
|
54
|
+
@output = cfile.readlines
|
55
|
+
else
|
56
|
+
@output = ::IO::popen(cmd).readlines
|
57
|
+
cfile.parent.mkpath
|
58
|
+
stack "saving output to cache file: #{cfile}".cyan
|
59
|
+
File.put_via_temp_file cfile do
|
60
|
+
output
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
#!/usr/bin/ruby -w
|
2
|
+
# -*- ruby -*-
|
3
|
+
|
4
|
+
module PVN
|
5
|
+
class CommandLine
|
6
|
+
include Loggable
|
7
|
+
|
8
|
+
attr_reader :output
|
9
|
+
attr_accessor :use_cache
|
10
|
+
|
11
|
+
def initialize use_cache, args = Array.new
|
12
|
+
@args = args.dup
|
13
|
+
@use_cache = use_cache
|
14
|
+
end
|
15
|
+
|
16
|
+
def use_cache?
|
17
|
+
@use_cache
|
18
|
+
end
|
19
|
+
|
20
|
+
def cache_dir
|
21
|
+
nil
|
22
|
+
end
|
23
|
+
|
24
|
+
def << arg
|
25
|
+
@args << arg
|
26
|
+
end
|
27
|
+
|
28
|
+
def execute
|
29
|
+
if use_cache?
|
30
|
+
run_cached_command
|
31
|
+
else
|
32
|
+
@output = ::IO.popen(to_command).readlines
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def to_command
|
37
|
+
@args.join ' '
|
38
|
+
end
|
39
|
+
|
40
|
+
def run args
|
41
|
+
if use_cache?
|
42
|
+
run_cached_command
|
43
|
+
else
|
44
|
+
super
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def get_cache_file
|
49
|
+
pwd = Pathname.pwd.split_path.join('')
|
50
|
+
info "pwd: #{pwd}"
|
51
|
+
Pathname.new(cache_dir) + pwd + @args.join('-')
|
52
|
+
end
|
53
|
+
|
54
|
+
def run_cached_command
|
55
|
+
stack "@args: #{@args}".cyan
|
56
|
+
cachefile = get_cache_file
|
57
|
+
if cachefile.exist?
|
58
|
+
debug "reading from cache file: #{cachefile}".cyan
|
59
|
+
@output = cachefile.readlines
|
60
|
+
else
|
61
|
+
@output = IO.popen(to_command).readlines
|
62
|
+
cachefile.parent.mkpath
|
63
|
+
debug "saving output to cache file: #{cachefile}".on_cyan
|
64
|
+
File.put_via_temp_file cachefile do
|
65
|
+
@output
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|