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