svnx 2.0.6 → 2.1.0

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.
Files changed (70) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.zshrc +2 -0
  4. data/Rakefile +2 -3
  5. data/lib/cmdline/arg.rb +12 -0
  6. data/lib/cmdline/cachefile.rb +37 -0
  7. data/lib/cmdline/caching.rb +25 -0
  8. data/lib/cmdline/filename.rb +16 -0
  9. data/lib/cmdline/gzpathname.rb +26 -0
  10. data/lib/cmdline/line.rb +57 -0
  11. data/lib/svnx/base/action.rb +31 -61
  12. data/lib/svnx/base/action_status.rb +37 -0
  13. data/lib/svnx/base/cmd.rb +20 -0
  14. data/lib/svnx/base/cmdline.rb +43 -37
  15. data/lib/svnx/base/command.rb +57 -50
  16. data/lib/svnx/base/command_factory.rb +24 -0
  17. data/lib/svnx/base/entries.rb +42 -40
  18. data/lib/svnx/base/entry.rb +46 -44
  19. data/lib/svnx/base/env.rb +14 -15
  20. data/lib/svnx/base/options.rb +22 -10
  21. data/lib/svnx/cat/command.rb +4 -2
  22. data/lib/svnx/cat/options.rb +11 -14
  23. data/lib/svnx/commit/command.rb +4 -2
  24. data/lib/svnx/commit/options.rb +11 -16
  25. data/lib/svnx/diff/command.rb +9 -7
  26. data/lib/svnx/diff/elements.rb +56 -54
  27. data/lib/svnx/diff/options.rb +14 -21
  28. data/lib/svnx/diff/parser.rb +73 -71
  29. data/lib/svnx/info/command.rb +4 -2
  30. data/lib/svnx/info/entries.rb +8 -6
  31. data/lib/svnx/info/entry.rb +23 -17
  32. data/lib/svnx/info/options.rb +11 -14
  33. data/lib/svnx/io/directory.rb +3 -1
  34. data/lib/svnx/io/element.rb +88 -86
  35. data/lib/svnx/log/command.rb +4 -2
  36. data/lib/svnx/log/entries.rb +14 -12
  37. data/lib/svnx/log/entry.rb +36 -58
  38. data/lib/svnx/log/entrypath.rb +35 -0
  39. data/lib/svnx/log/options.rb +14 -18
  40. data/lib/svnx/merge/command.rb +4 -2
  41. data/lib/svnx/merge/options.rb +17 -22
  42. data/lib/svnx/project.rb +27 -15
  43. data/lib/svnx/propget/command.rb +4 -2
  44. data/lib/svnx/propget/entries.rb +8 -6
  45. data/lib/svnx/propget/entry.rb +12 -10
  46. data/lib/svnx/propget/options.rb +13 -17
  47. data/lib/svnx/propset/command.rb +4 -2
  48. data/lib/svnx/propset/options.rb +14 -19
  49. data/lib/svnx/revision/argfactory.rb +6 -2
  50. data/lib/svnx/revision/argument.rb +22 -19
  51. data/lib/svnx/revision/date.rb +16 -16
  52. data/lib/svnx/revision/error.rb +4 -1
  53. data/lib/svnx/revision/range.rb +2 -1
  54. data/lib/svnx/status/command.rb +4 -2
  55. data/lib/svnx/status/entries.rb +13 -11
  56. data/lib/svnx/status/entry.rb +37 -39
  57. data/lib/svnx/status/options.rb +12 -15
  58. data/lib/svnx/update/command.rb +4 -2
  59. data/lib/svnx/update/options.rb +11 -12
  60. data/lib/svnx/util/classutil.rb +19 -0
  61. data/lib/svnx/util/dateutil.rb +1 -0
  62. data/lib/svnx/util/objutil.rb +36 -6
  63. data/lib/svnx/version.rb +1 -1
  64. data/repackage +1 -0
  65. data/svnx.gemspec +6 -5
  66. metadata +29 -6
  67. data/lib/system/command/arg.rb +0 -13
  68. data/lib/system/command/cachefile.rb +0 -58
  69. data/lib/system/command/caching.rb +0 -23
  70. data/lib/system/command/line.rb +0 -58
@@ -2,68 +2,75 @@
2
2
  # -*- ruby -*-
3
3
 
4
4
  require 'logue/loggable'
5
- require 'system/command/caching'
5
+ require 'cmdline/caching'
6
6
  require 'svnx/base/cmdline'
7
+ require 'svnx/util/classutil'
8
+ require 'svnx/base/command_factory'
7
9
 
8
- class Svnx::Base::Command
9
- include Logue::Loggable
10
-
11
- class << self
12
- def caching
13
- define_method :caching? do
14
- true
10
+ module Svnx::Base
11
+ class Command
12
+ include Logue::Loggable
13
+
14
+ class << self
15
+ def caching
16
+ define_method :caching? do
17
+ true
18
+ end
15
19
  end
16
- end
17
20
 
18
- def noncaching
19
- define_method :caching? do
20
- false
21
+ def noncaching
22
+ define_method :caching? do
23
+ false
24
+ end
21
25
  end
22
26
  end
23
- end
24
-
25
- attr_reader :output
26
- attr_reader :error
27
- attr_reader :status
28
-
29
- def initialize options, cls: Svnx::Base::CommandLine, exec: nil, xml: false, caching: caching?
30
- melements = module_elements
31
- modl = find_module melements
32
- opts = modl::Options.new options
33
- cmdargs = opts.to_args
34
- subcommand = melements[-1].downcase
35
-
36
- @cmdline = exec || cls.new(subcommand: subcommand, xml: xml, caching: caching, args: cmdargs)
37
-
38
- @output = @cmdline.execute
39
- @error = @cmdline.error
40
- @status = @cmdline.status
41
- end
42
27
 
43
- def module_elements
44
- mods = self.class.name.split "::"
45
- mods[0 .. -2]
46
- end
28
+ attr_reader :output
29
+ attr_reader :error
30
+ attr_reader :status
47
31
 
48
- def find_module elements = module_elements
49
- mod = elements * "::"
50
- Kernel.const_get mod
32
+ attr_reader :options
33
+
34
+ def initialize options, cls: nil, optcls: nil, exec: nil, xml: false, caching: caching?
35
+ factory = CommandFactory.new
36
+ params = factory.create self.class, cmdlinecls: cls, optcls: optcls
37
+
38
+ optcls ||= params[:options_class]
39
+
40
+ @options = optcls.new options
41
+ cmdargs = @options.to_args
42
+ subcommand = params[:subcommand]
43
+
44
+ cls ||= params[:command_line_class]
45
+
46
+ @cmdline = exec || cls.new(subcommand: subcommand, xml: xml, caching: caching, args: cmdargs)
47
+ debug "@cmdline: #{@cmdline}"
48
+
49
+ @output = @cmdline.execute
50
+ debug "@output: #{@output}"
51
+
52
+ @error = @cmdline.error
53
+ debug "@error: #{@error}"
54
+
55
+ @status = @cmdline.status
56
+ debug "@status: #{@status}"
57
+ end
51
58
  end
52
- end
53
59
 
54
- class Svnx::Base::EntriesCommand < Svnx::Base::Command
55
- attr_reader :entries
56
-
57
- def initialize options, cls: Svnx::Base::CommandLine, exec: nil, caching: caching?, xml: true, entries_class: nil
58
- super options, cls: cls, exec: exec, xml: xml, caching: caching
60
+ class EntriesCommand < Command
61
+ attr_reader :entries
59
62
 
60
- if not @output.empty?
61
- entries_class ||= begin
62
- modl = find_module
63
- modl::Entries
64
- end
63
+ def initialize options, cls: CommandLine, exec: nil, caching: caching?, xml: true, entries_class: nil
64
+ super options, cls: cls, exec: exec, xml: xml, caching: caching
65
65
 
66
- @entries = entries_class.new lines: @output
66
+ if not @output.empty?
67
+ entries_class ||= begin
68
+ modl = ClassUtil::Util.find_module self.class
69
+ modl::Entries
70
+ end
71
+
72
+ @entries = entries_class.new lines: @output
73
+ end
67
74
  end
68
75
  end
69
76
  end
@@ -0,0 +1,24 @@
1
+ #!/usr/bin/ruby -w
2
+ # -*- ruby -*-
3
+
4
+ require 'svnx/base/cmdline'
5
+ require 'svnx/util/classutil'
6
+
7
+ module Svnx::Base
8
+ class CommandFactory
9
+ include Logue::Loggable
10
+
11
+ def create cmdcls, cmdlinecls: nil, optcls: nil
12
+ melements = ClassUtil::Util.module_elements cmdcls
13
+
14
+ optcls ||= begin
15
+ modl = ClassUtil::Util.find_module cmdcls
16
+ modl::Options
17
+ end
18
+
19
+ cmdlinecls ||= CommandLine
20
+
21
+ { options_class: optcls, subcommand: melements[-1].downcase, command_line_class: cmdlinecls }
22
+ end
23
+ end
24
+ end
@@ -12,58 +12,60 @@ end
12
12
  # this is a parse/process on-demand list of entries, acting like an
13
13
  # Enumerable.
14
14
 
15
- class Svnx::Base::Entries
16
- include Logue::Loggable, Enumerable
15
+ module Svnx::Base
16
+ class Entries
17
+ include Logue::Loggable, Enumerable
17
18
 
18
- attr_reader :size
19
+ attr_reader :size
19
20
 
20
- def initialize xmllines: nil, lines: nil
21
- # it's a hash, but indexed with integers, for non-sequential access:
22
- @entries = Hash.new
21
+ def initialize xmllines: nil, lines: nil
22
+ # it's a hash, but indexed with integers, for non-sequential access:
23
+ @entries = Hash.new
23
24
 
24
- lines ||= xmllines
25
+ lines ||= xmllines
25
26
 
26
- if lines.kind_of? Array
27
- lines = lines.join ''
28
- end
29
-
30
- doc = REXML::Document.new lines
31
-
32
- @elements = get_elements doc
33
- @size = @elements.size
34
- end
27
+ if lines.kind_of? Array
28
+ lines = lines.join ''
29
+ end
35
30
 
36
- def get_elements doc
37
- raise "get_elements must be implemented for: #{self.class}"
38
- end
31
+ doc = REXML::Document.new lines
32
+
33
+ @elements = get_elements doc
34
+ @size = @elements.size
35
+ end
39
36
 
40
- def create_entry xmlelement
41
- raise "create_entry must be implemented for: #{self.class}"
42
- end
37
+ def get_elements doc
38
+ raise "get_elements must be implemented for: #{self.class}"
39
+ end
43
40
 
44
- # this doesn't handle negative indices
45
- def [] idx
46
- if entry = @entries[idx]
47
- return entry
41
+ def create_entry xmlelement
42
+ raise "create_entry must be implemented for: #{self.class}"
48
43
  end
49
- if idx < 0 || idx >= size
50
- raise "error: index #{idx} is not in range(0 .. #{size})"
44
+
45
+ # this doesn't handle negative indices
46
+ def [] idx
47
+ if entry = @entries[idx]
48
+ return entry
49
+ end
50
+ if idx < 0 || idx >= size
51
+ raise "error: index #{idx} is not in range(0 .. #{size})"
52
+ end
53
+ @entries[idx] = create_entry @elements[idx + 1]
51
54
  end
52
- @entries[idx] = create_entry @elements[idx + 1]
53
- end
54
55
 
55
- def each(&blk)
56
- # all elements must be processed before each can run:
57
- if @elements
58
- # a little confusing here: REXML does each_with_index with idx
59
- # zero-based, but elements[0] is invalid.
60
- @elements.each_with_index do |element, idx|
61
- @entries[idx] ||= create_entry(element)
56
+ def each(&blk)
57
+ # all elements must be processed before each can run:
58
+ if @elements
59
+ # a little confusing here: REXML does each_with_index with idx
60
+ # zero-based, but elements[0] is invalid.
61
+ @elements.each_with_index do |element, idx|
62
+ @entries[idx] ||= create_entry(element)
63
+ end
64
+
65
+ @elements = nil
62
66
  end
63
67
 
64
- @elements = nil
68
+ @entries.keys.sort.collect { |idx| @entries[idx] }.each(&blk)
65
69
  end
66
-
67
- @entries.keys.sort.collect { |idx| @entries[idx] }.each(&blk)
68
70
  end
69
71
  end
@@ -9,62 +9,64 @@ module Svnx
9
9
  end
10
10
  end
11
11
 
12
- class Svnx::Base::Entry
13
- include Logue::Loggable
12
+ module Svnx::Base
13
+ class Entry
14
+ include Logue::Loggable
14
15
 
15
- def initialize xmllines: nil, xmlelement: nil
16
- if xmllines
17
- if xmllines.kind_of? Array
18
- xmllines = xmllines.join ''
16
+ def initialize xmllines: nil, xmlelement: nil
17
+ if xmllines
18
+ if xmllines.kind_of? Array
19
+ xmllines = xmllines.join ''
20
+ end
21
+ doc = REXML::Document.new xmllines
22
+ set_from_xml doc
23
+ elsif xmlelement
24
+ set_from_element xmlelement
25
+ else
26
+ raise "must be initialized with xmllines (received: #{xmllines.inspect}) or xmlelement (received: #{xmlelement.inspect})"
19
27
  end
20
- doc = REXML::Document.new xmllines
21
- set_from_xml doc
22
- elsif xmlelement
23
- set_from_element xmlelement
24
- else
25
- raise "must be initialized with xmllines (received: #{xmllines.inspect}) or xmlelement (received: #{xmlelement.inspect})"
26
28
  end
27
- end
28
29
 
29
- def set_from_xml xmldoc
30
- raise "must be implemented"
31
- end
30
+ def set_from_xml xmldoc
31
+ raise "must be implemented"
32
+ end
32
33
 
33
- def set_from_element elmt
34
- raise "must be implemented"
35
- end
34
+ def set_from_element elmt
35
+ raise "must be implemented"
36
+ end
36
37
 
37
- def set_attr_var xmlelement, varname
38
- set_var varname, attribute_value(xmlelement, varname)
39
- end
38
+ def set_attr_var xmlelement, varname
39
+ set_var varname, attribute_value(xmlelement, varname)
40
+ end
40
41
 
41
- def set_attr_vars xmlelement, *varnames
42
- varnames.each do |varname|
43
- set_attr_var xmlelement, varname
42
+ def set_attr_vars xmlelement, *varnames
43
+ varnames.each do |varname|
44
+ set_attr_var xmlelement, varname
45
+ end
44
46
  end
45
- end
46
47
 
47
- def set_elmt_var xmlelement, varname
48
- set_var varname, element_text(xmlelement, varname)
49
- end
48
+ def set_elmt_var xmlelement, varname
49
+ set_var varname, element_text(xmlelement, varname)
50
+ end
50
51
 
51
- def set_elmt_vars xmlelement, *varnames
52
- varnames.each do |varname|
53
- set_elmt_var xmlelement, varname
52
+ def set_elmt_vars xmlelement, *varnames
53
+ varnames.each do |varname|
54
+ set_elmt_var xmlelement, varname
55
+ end
54
56
  end
55
- end
56
57
 
57
- def set_var varname, value
58
- instance_variable_set '@' + varname.to_s, value
59
- end
58
+ def set_var varname, value
59
+ instance_variable_set '@' + varname.to_s, value
60
+ end
60
61
 
61
- def attribute_value xmlelement, attrname
62
- xmlelement.attributes[attrname.to_s]
63
- end
62
+ def attribute_value xmlelement, attrname
63
+ xmlelement.attributes[attrname.to_s]
64
+ end
64
65
 
65
- def element_text xmlelement, elmtname
66
- elmt = xmlelement.elements[elmtname.to_s]
67
- # some elements don't have text:
68
- (elmt && elmt.text) || ""
69
- end
66
+ def element_text xmlelement, elmtname
67
+ elmt = xmlelement.elements[elmtname.to_s]
68
+ # some elements don't have text:
69
+ (elmt && elmt.text) || ""
70
+ end
71
+ end
70
72
  end
@@ -4,23 +4,22 @@
4
4
  require 'singleton'
5
5
 
6
6
  module Svnx
7
- end
8
-
9
- class Svnx::Env
10
- include Singleton
7
+ class Env
8
+ include Singleton
11
9
 
12
- # the directory into which to put cached files
13
- attr_accessor :cache_dir_name
10
+ # the directory into which to put cached files
11
+ attr_accessor :cache_dir_name
14
12
 
15
- # the environment variable, naming the cache directory
16
- attr_accessor :cache_dir_env_varname
17
-
18
- def initialize
19
- @cache_dir_name = "/tmp/svnx"
20
- @cache_dir_env_varname = "SVNX_TMP_DIR"
21
- end
13
+ # the environment variable, naming the cache directory
14
+ attr_accessor :cache_dir_env_varname
15
+
16
+ def initialize
17
+ @cache_dir_name = "/tmp/svnx"
18
+ @cache_dir_env_varname = "SVNX_TMP_DIR"
19
+ end
22
20
 
23
- def cache_dir
24
- ENV[@cache_dir_env_varname] || @cache_dir_name
21
+ def cache_dir
22
+ ENV[@cache_dir_env_varname] || @cache_dir_name
23
+ end
25
24
  end
26
25
  end
@@ -8,16 +8,28 @@ module Svnx
8
8
  end
9
9
  end
10
10
 
11
- class Svnx::Base::Options
12
- include Svnx::ObjectUtil
13
-
14
- def to_args
15
- Array.new.tap do |args|
16
- options_to_args.each do |opt|
17
- optname = opt[0]
18
- values = opt[1]
19
- if send optname
20
- args.concat [ values ].flatten
11
+ module Svnx::Base
12
+ class Options
13
+ include Svnx::ObjectUtil
14
+
15
+ def check args, valid = Array.new
16
+ invalid = args.keys.reject do |field|
17
+ valid.include? field
18
+ end
19
+
20
+ unless invalid.empty?
21
+ raise "invalid fields for #{self.class}: #{invalid.join(' ')}"
22
+ end
23
+ end
24
+
25
+ def to_args
26
+ Array.new.tap do |args|
27
+ options_to_args.each do |opt|
28
+ optname = opt[0]
29
+ values = opt[1]
30
+ if send optname
31
+ args.concat [ values ].flatten
32
+ end
21
33
  end
22
34
  end
23
35
  end
@@ -4,6 +4,8 @@
4
4
  require 'svnx/cat/options'
5
5
  require 'svnx/base/command'
6
6
 
7
- class Svnx::Cat::Command < Svnx::Base::Command
8
- caching
7
+ module Svnx::Cat
8
+ class Command < Svnx::Base::Command
9
+ caching
10
+ end
9
11
  end