pvn 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (99) hide show
  1. data/README.markdown +38 -0
  2. data/bin/pvn +12 -0
  3. data/bin/pvndiff +10 -0
  4. data/lib/pvn/app.rb +144 -0
  5. data/lib/pvn/base/textlines.rb +35 -0
  6. data/lib/pvn/base/util.rb +14 -0
  7. data/lib/pvn/cmddoc.rb +77 -0
  8. data/lib/pvn/config.rb +65 -0
  9. data/lib/pvn/describe.rb +40 -0
  10. data/lib/pvn/diff/diffcmd.rb +49 -0
  11. data/lib/pvn/diff/differ.rb +67 -0
  12. data/lib/pvn/diff/diffopts.rb +58 -0
  13. data/lib/pvn/doc.rb +34 -0
  14. data/lib/pvn/io/element.rb +113 -0
  15. data/lib/pvn/io/fselement.rb +22 -0
  16. data/lib/pvn/log/formatter/color_formatter.rb +29 -0
  17. data/lib/pvn/log/formatter/entries_formatter.rb +33 -0
  18. data/lib/pvn/log/formatter/entry_formatter.rb +57 -0
  19. data/lib/pvn/log/formatter/log_formatter.rb +59 -0
  20. data/lib/pvn/log/formatter/message_formatter.rb +19 -0
  21. data/lib/pvn/log/formatter/path_formatter.rb +41 -0
  22. data/lib/pvn/log/formatter/summary_formatter.rb +49 -0
  23. data/lib/pvn/log/logcmd.rb +136 -0
  24. data/lib/pvn/log/logentry.rb +116 -0
  25. data/lib/pvn/log/logfactory.rb +101 -0
  26. data/lib/pvn/log/logoptions.rb +43 -0
  27. data/lib/pvn/pct/linecount.rb +33 -0
  28. data/lib/pvn/pct/pctcmd.rb +204 -0
  29. data/lib/pvn/pct/statcmd.rb +13 -0
  30. data/lib/pvn/revision/entry.rb +94 -0
  31. data/lib/pvn/revision.rb +119 -0
  32. data/lib/pvn/subcommands/base/clargs.rb +53 -0
  33. data/lib/pvn/subcommands/base/command.rb +60 -0
  34. data/lib/pvn/subcommands/base/doc.rb +94 -0
  35. data/lib/pvn/subcommands/base/options.rb +22 -0
  36. data/lib/pvn/subcommands/log/command.rb +70 -0
  37. data/lib/pvn/subcommands/log/options.rb +43 -0
  38. data/lib/pvn/subcommands/pct/clargs.rb +33 -0
  39. data/lib/pvn/subcommands/pct/command.rb +57 -0
  40. data/lib/pvn/subcommands/revision/multiple_revisions_option.rb +43 -0
  41. data/lib/pvn/subcommands/revision/revision_option.rb +74 -0
  42. data/lib/pvn/subcommands/revision/revision_regexp_option.rb +39 -0
  43. data/lib/pvn/svn/command/svncmd.rb +39 -0
  44. data/lib/pvn/svn/environment.rb +23 -0
  45. data/lib/pvn/svn/svnelement.rb +89 -0
  46. data/lib/pvn/svn/svninfo.rb +42 -0
  47. data/lib/pvn/svn/svnroot.rb +29 -0
  48. data/lib/pvn/upp/uppcmd.rb +112 -0
  49. data/lib/pvn/wherecmd.rb +55 -0
  50. data/lib/pvn.rb +8 -0
  51. data/lib/svnx/command.rb +60 -0
  52. data/lib/svnx/entry.rb +34 -0
  53. data/lib/svnx/info/command.rb +21 -0
  54. data/lib/svnx/info/entries.rb +27 -0
  55. data/lib/svnx/info/entry.rb +34 -0
  56. data/lib/svnx/log/command.rb +93 -0
  57. data/lib/svnx/log/entries.rb +57 -0
  58. data/lib/svnx/log/entry.rb +54 -0
  59. data/lib/svnx/status/command.rb +21 -0
  60. data/lib/svnx/status/entries.rb +22 -0
  61. data/lib/svnx/status/entry.rb +33 -0
  62. data/lib/synoption/base_option.rb +149 -0
  63. data/lib/synoption/boolean_option.rb +21 -0
  64. data/lib/synoption/doc.rb +81 -0
  65. data/lib/synoption/fixnum_option.rb +13 -0
  66. data/lib/synoption/match.rb +47 -0
  67. data/lib/synoption/option.rb +10 -0
  68. data/lib/synoption/optionable.rb +66 -0
  69. data/lib/synoption/set.rb +114 -0
  70. data/lib/system/cachecmd.rb +65 -0
  71. data/lib/system/cmdexec.rb +13 -0
  72. data/lib/system/cmdline.rb +70 -0
  73. data/lib/system/command/arg.rb +12 -0
  74. data/lib/system/command/cachefile.rb +39 -0
  75. data/lib/system/command/caching.rb +36 -0
  76. data/lib/system/command/line.rb +47 -0
  77. data/lib/system/command.rb +72 -0
  78. data/test/integration/svnx/log/test.rb +43 -0
  79. data/test/unit/pvn/app_test.rb +22 -0
  80. data/test/unit/pvn/io/element/log/log_test.rb +35 -0
  81. data/test/unit/pvn/log/formatter/entry_formatter_test.rb +90 -0
  82. data/test/unit/pvn/revision/entry_test.rb +123 -0
  83. data/test/unit/pvn/subcommands/log/command_test.rb +22 -0
  84. data/test/unit/pvn/subcommands/log/options_test.rb +85 -0
  85. data/test/unit/pvn/subcommands/revision/multiple_revisions_option_test.rb +67 -0
  86. data/test/unit/pvn/subcommands/revision/revision_option_test.rb +57 -0
  87. data/test/unit/pvn/subcommands/revision/revision_regexp_option_test.rb +69 -0
  88. data/test/unit/svnx/info/entry_test.rb +52 -0
  89. data/test/unit/svnx/log/cmargs_test.rb +22 -0
  90. data/test/unit/svnx/log/entries_test.rb +73 -0
  91. data/test/unit/svnx/log/entry_test.rb +21 -0
  92. data/test/unit/svnx/status/entry_test.rb +39 -0
  93. data/test/unit/synoption/base_option_test.rb +182 -0
  94. data/test/unit/synoption/match_test.rb +61 -0
  95. data/test/unit/synoption/option_test.rb +15 -0
  96. data/test/unit/synoption/set_test.rb +37 -0
  97. data/test/unit/system/command/caching_test.rb +97 -0
  98. data/test/unit/system/command/line_test.rb +33 -0
  99. 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,13 @@
1
+ #!/usr/bin/ruby -w
2
+ # -*- ruby -*-
3
+
4
+ require 'synoption/option'
5
+
6
+ module PVN
7
+ # An option that has a fixnum (integer) as its value.
8
+ class FixnumOption < Option
9
+ def set_value val
10
+ super val.to_i
11
+ end
12
+ end
13
+ 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,10 @@
1
+ #!/usr/bin/ruby -w
2
+ # -*- ruby -*-
3
+
4
+ require 'synoption/base_option'
5
+
6
+ module PVN
7
+ class Option < BaseOption
8
+ include Loggable
9
+ end
10
+ 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,13 @@
1
+ #!/usr/bin/ruby -w
2
+ # -*- ruby -*-
3
+
4
+ module PVN
5
+ class CommandExecutor
6
+ def initialize
7
+ end
8
+
9
+ def run cmd
10
+ IO.popen(cmd).readlines
11
+ end
12
+ end
13
+ 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
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/ruby -w
2
+ # -*- ruby -*-
3
+
4
+ module System
5
+ class Argument < String
6
+ # just a string, but quotes itself
7
+
8
+ def to_s
9
+ '"' + super + '"'
10
+ end
11
+ end
12
+ end