svnx 1.0.1 → 2.0.6
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.
- checksums.yaml +4 -4
- data/.gitignore +2 -0
- data/.glarkrc +1 -0
- data/Features.txt +7 -0
- data/Gemfile +4 -0
- data/History.txt +4 -0
- data/LICENSE +20 -0
- data/Manifest.txt +0 -0
- data/README.md +12 -0
- data/Rakefile +12 -0
- data/lib/svnx/base/action.rb +57 -52
- data/lib/svnx/base/cmdline.rb +58 -0
- data/lib/svnx/base/command.rb +49 -41
- data/lib/svnx/base/entries.rb +46 -45
- data/lib/svnx/base/entry.rb +51 -38
- data/lib/svnx/base/env.rb +26 -0
- data/lib/svnx/base/options.rb +25 -0
- data/lib/svnx/cat/command.rb +3 -64
- data/lib/svnx/cat/options.rb +28 -0
- data/lib/svnx/commit/command.rb +9 -0
- data/lib/svnx/commit/options.rb +29 -0
- data/lib/svnx/diff/command.rb +17 -0
- data/lib/svnx/diff/elements.rb +84 -0
- data/lib/svnx/diff/options.rb +35 -0
- data/lib/svnx/diff/parser.rb +105 -0
- data/lib/svnx/info/command.rb +4 -47
- data/lib/svnx/info/entries.rb +6 -8
- data/lib/svnx/info/entry.rb +21 -23
- data/lib/svnx/info/options.rb +28 -0
- data/lib/svnx/io/directory.rb +9 -5
- data/lib/svnx/io/element.rb +93 -95
- data/lib/svnx/log/command.rb +7 -3
- data/lib/svnx/log/entries.rb +17 -14
- data/lib/svnx/log/entry.rb +61 -49
- data/lib/svnx/log/options.rb +31 -0
- data/lib/svnx/merge/command.rb +9 -0
- data/lib/svnx/merge/options.rb +34 -0
- data/lib/svnx/project.rb +74 -0
- data/lib/svnx/propget/command.rb +9 -0
- data/lib/svnx/propget/entries.rb +15 -0
- data/lib/svnx/propget/entry.rb +23 -0
- data/lib/svnx/propget/options.rb +31 -0
- data/lib/svnx/propset/command.rb +9 -0
- data/lib/svnx/propset/options.rb +33 -0
- data/lib/svnx/revision/argfactory.rb +2 -2
- data/lib/svnx/revision/argument.rb +7 -3
- data/lib/svnx/revision/date.rb +27 -0
- data/lib/svnx/revision/error.rb +2 -2
- data/lib/svnx/revision/range.rb +5 -2
- data/lib/svnx/status/command.rb +4 -42
- data/lib/svnx/status/entries.rb +11 -12
- data/lib/svnx/status/entry.rb +43 -41
- data/lib/svnx/status/options.rb +28 -0
- data/lib/svnx/update/command.rb +9 -0
- data/lib/svnx/update/options.rb +25 -0
- data/lib/svnx/util/dateutil.rb +35 -0
- data/lib/svnx/util/objutil.rb +14 -0
- data/lib/{svnx.rb → svnx/version.rb} +2 -2
- data/lib/system/command/arg.rb +6 -5
- data/lib/system/command/cachefile.rb +29 -21
- data/lib/system/command/caching.rb +12 -25
- data/lib/system/command/line.rb +41 -30
- data/svnx.gemspec +34 -0
- metadata +85 -61
- data/lib/svnx/base/args.rb +0 -24
- data/lib/svnx/log/args.rb +0 -57
- data/lib/svnx/log/exec.rb +0 -27
- data/lib/svnx/log/line.rb +0 -42
- data/test/integration/info/info_test.rb +0 -21
- data/test/integration/log/log_test.rb +0 -74
- data/test/integration/status/status_test.rb +0 -35
- data/test/integration/svnx/io/element_test.rb +0 -235
- data/test/unit/svnx/base/action_test.rb +0 -49
- data/test/unit/svnx/cat/command_test.rb +0 -55
- data/test/unit/svnx/info/entries_test.rb +0 -22
- data/test/unit/svnx/log/args_test.rb +0 -15
- data/test/unit/svnx/log/entries_test.rb +0 -87
- data/test/unit/svnx/log/entry_test.rb +0 -15
- data/test/unit/svnx/log/exec_test.rb +0 -15
- data/test/unit/svnx/log/line_test.rb +0 -14
- data/test/unit/svnx/revision/argfactory_test.rb +0 -50
- data/test/unit/svnx/revision/argument_test.rb +0 -167
- data/test/unit/svnx/revision/range_test.rb +0 -48
- data/test/unit/svnx/status/entries_test.rb +0 -20
- data/test/unit/system/command/cachefile_test.rb +0 -52
- data/test/unit/system/command/caching_test.rb +0 -92
- data/test/unit/system/command/line_test.rb +0 -63
@@ -0,0 +1,105 @@
|
|
1
|
+
#!/usr/bin/ruby -w
|
2
|
+
# -*- ruby -*-
|
3
|
+
|
4
|
+
require 'logue/loggable'
|
5
|
+
require 'svnx/diff/elements'
|
6
|
+
|
7
|
+
class Svnx::Diff::Parser
|
8
|
+
include Logue::Loggable
|
9
|
+
|
10
|
+
def parse_header_file lines
|
11
|
+
re = Regexp.new '^[\-\+]{3} (.*)\t\((?:nonexistent|revision (\d+))\)'
|
12
|
+
if md = re.match(lines.first)
|
13
|
+
lines.shift
|
14
|
+
Svnx::Diff::File.new filename: md[1], revision: md[2] && md[2].to_i
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def parse_header_section lines
|
19
|
+
re = Regexp.new '^Index: (.*)'
|
20
|
+
if md = re.match(lines.first)
|
21
|
+
filename = md[1]
|
22
|
+
lines.shift
|
23
|
+
|
24
|
+
# discard the ==== line:
|
25
|
+
lines.shift
|
26
|
+
|
27
|
+
from = parse_header_file lines
|
28
|
+
to = parse_header_file lines
|
29
|
+
|
30
|
+
Svnx::Diff::Header.new filename: filename, from: from, to: to
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def parse_ranges lines
|
35
|
+
range_re = Regexp.new '@@ \-(\d+)(?:,(\d+))? \+(\d+)(?:,(\d+))? @@'
|
36
|
+
if md = range_re.match(lines.first)
|
37
|
+
lines.shift
|
38
|
+
|
39
|
+
from, to = [ 1, 3 ].collect do |idx|
|
40
|
+
Svnx::Diff::HunkRange.new md[idx].to_i, (md[idx + 1] || 1).to_i
|
41
|
+
end
|
42
|
+
|
43
|
+
Svnx::Diff::HunkRanges.new from, to
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def parse_hunk lines
|
48
|
+
if ranges = parse_ranges(lines)
|
49
|
+
Svnx::Diff::Hunk.new(ranges, Array.new).tap do |hunk|
|
50
|
+
char_to_type = { ' ' => :context, '+' => :added, '-' => :deleted }
|
51
|
+
|
52
|
+
while !lines.empty?
|
53
|
+
if lines.first == "\"
|
54
|
+
hunk.lines << [ :context, :no_newline ]
|
55
|
+
lines.shift
|
56
|
+
elsif type = char_to_type[lines.first[0]]
|
57
|
+
hunk.lines << [ type, lines.shift[1 .. -1] ]
|
58
|
+
else
|
59
|
+
break
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def parse_hunks lines
|
67
|
+
Array.new.tap do |hunks|
|
68
|
+
while !lines.empty?
|
69
|
+
if hunk = parse_hunk(lines)
|
70
|
+
hunks << hunk
|
71
|
+
else
|
72
|
+
break
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def parse_file_diff lines
|
79
|
+
if header = parse_header_section(lines)
|
80
|
+
SvnFileDiff.new(header).tap do |diff|
|
81
|
+
if header.from && header.to
|
82
|
+
while !lines.empty?
|
83
|
+
if hunk = parse_hunk(lines)
|
84
|
+
diff.hunks << hunk
|
85
|
+
else
|
86
|
+
break
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def parse_all_output lines
|
95
|
+
Array.new.tap do |diffs|
|
96
|
+
until lines.empty?
|
97
|
+
if filediff = parse_file_diff(lines)
|
98
|
+
diffs << filediff
|
99
|
+
else
|
100
|
+
break
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
data/lib/svnx/info/command.rb
CHANGED
@@ -1,53 +1,10 @@
|
|
1
1
|
#!/usr/bin/ruby -w
|
2
2
|
# -*- ruby -*-
|
3
3
|
|
4
|
-
require 'svnx/
|
4
|
+
require 'svnx/info/options'
|
5
5
|
require 'svnx/info/entries'
|
6
|
+
require 'svnx/base/command'
|
6
7
|
|
7
|
-
|
8
|
-
|
9
|
-
def initialize args = Array.new
|
10
|
-
super "info", args.to_a
|
11
|
-
end
|
12
|
-
end
|
13
|
-
|
14
|
-
class InfoCommandArgs < CommandArgs
|
15
|
-
attr_reader :revision
|
16
|
-
|
17
|
-
def initialize args = Hash.new
|
18
|
-
@revision = args[:revision]
|
19
|
-
super
|
20
|
-
end
|
21
|
-
|
22
|
-
def to_a
|
23
|
-
ary = Array.new
|
24
|
-
|
25
|
-
if @revision
|
26
|
-
[ @revision ].flatten.each do |rev|
|
27
|
-
ary << "-r#{rev}"
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
if @path
|
32
|
-
ary << @path
|
33
|
-
end
|
34
|
-
ary
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
class InfoCommand < Command
|
39
|
-
def command_line
|
40
|
-
InfoCommandLine.new @args
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
class InfoExec
|
45
|
-
attr_reader :entry
|
46
|
-
|
47
|
-
def initialize args
|
48
|
-
cmd = InfoCommand.new InfoCommandArgs.new(args)
|
49
|
-
# info has only one entry
|
50
|
-
@entry = SVNx::Info::Entries.new(:xmllines => cmd.execute)[0]
|
51
|
-
end
|
52
|
-
end
|
8
|
+
class Svnx::Info::Command < Svnx::Base::EntriesCommand
|
9
|
+
noncaching
|
53
10
|
end
|
data/lib/svnx/info/entries.rb
CHANGED
@@ -4,14 +4,12 @@
|
|
4
4
|
require 'svnx/info/entry'
|
5
5
|
require 'svnx/base/entries'
|
6
6
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
end
|
7
|
+
class Svnx::Info::Entries < Svnx::Base::Entries
|
8
|
+
def get_elements doc
|
9
|
+
doc.elements['info'].elements
|
10
|
+
end
|
12
11
|
|
13
|
-
|
14
|
-
|
15
|
-
end
|
12
|
+
def create_entry xmlelement
|
13
|
+
Svnx::Info::Entry.new :xmlelement => xmlelement
|
16
14
|
end
|
17
15
|
end
|
data/lib/svnx/info/entry.rb
CHANGED
@@ -3,32 +3,30 @@
|
|
3
3
|
|
4
4
|
require 'svnx/base/entry'
|
5
5
|
|
6
|
-
module
|
6
|
+
module Svnx
|
7
|
+
module Info
|
8
|
+
end
|
9
|
+
end
|
7
10
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
attr_reader :wc_root
|
11
|
+
class Svnx::Info::Entry < Svnx::Base::Entry
|
12
|
+
attr_reader :url
|
13
|
+
attr_reader :root
|
14
|
+
attr_reader :kind
|
15
|
+
attr_reader :path
|
16
|
+
attr_reader :revision
|
17
|
+
attr_reader :wc_root
|
16
18
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
repo = elmt.elements['repository']
|
25
|
-
set_elmt_var repo, 'root'
|
19
|
+
def set_from_element elmt
|
20
|
+
set_attr_vars elmt, 'kind', 'path', 'revision'
|
21
|
+
set_elmt_var elmt, 'url'
|
22
|
+
|
23
|
+
repo = elmt.elements['repository']
|
24
|
+
set_elmt_var repo, 'root'
|
26
25
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
end
|
26
|
+
@wc_root = nil
|
27
|
+
if wcinfo = elmt.elements['wc-info']
|
28
|
+
if wcroot = wcinfo.elements['wcroot-abspath']
|
29
|
+
@wc_root = wcroot.text
|
32
30
|
end
|
33
31
|
end
|
34
32
|
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
#!/usr/bin/ruby -w
|
2
|
+
# -*- ruby -*-
|
3
|
+
|
4
|
+
require 'svnx/util/objutil'
|
5
|
+
require 'svnx/base/options'
|
6
|
+
|
7
|
+
module Svnx
|
8
|
+
module Info
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
class Svnx::Info::Options < Svnx::Base::Options
|
13
|
+
attr_reader :revision
|
14
|
+
attr_reader :url
|
15
|
+
attr_reader :path
|
16
|
+
|
17
|
+
def initialize args
|
18
|
+
assign args, :revision, :url, :path
|
19
|
+
end
|
20
|
+
|
21
|
+
def options_to_args
|
22
|
+
Array.new.tap do |optargs|
|
23
|
+
optargs << [ :revision, [ "-r", revision ] ]
|
24
|
+
optargs << [ :url, url ]
|
25
|
+
optargs << [ :path, path ]
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
data/lib/svnx/io/directory.rb
CHANGED
@@ -1,10 +1,14 @@
|
|
1
1
|
#!/usr/bin/ruby -w
|
2
2
|
# -*- ruby -*-
|
3
3
|
|
4
|
-
module
|
5
|
-
|
6
|
-
# which should exist).
|
7
|
-
|
8
|
-
class Directory < Element
|
4
|
+
module Svnx
|
5
|
+
module IO
|
9
6
|
end
|
10
7
|
end
|
8
|
+
|
9
|
+
|
10
|
+
# An element unites an svn element and a file/directory (at least one of
|
11
|
+
# which should exist).
|
12
|
+
|
13
|
+
class Svnx::IO::Directory < Element
|
14
|
+
end
|
data/lib/svnx/io/element.rb
CHANGED
@@ -1,127 +1,125 @@
|
|
1
1
|
#!/usr/bin/ruby -w
|
2
2
|
# -*- ruby -*-
|
3
3
|
|
4
|
-
require 'rubygems'
|
5
4
|
require 'logue/loggable'
|
6
|
-
require 'svnx/log/
|
7
|
-
require 'svnx/status/entries'
|
5
|
+
require 'svnx/log/command'
|
8
6
|
require 'svnx/status/command'
|
9
|
-
require 'svnx/info/entries'
|
10
7
|
require 'svnx/info/command'
|
11
8
|
require 'svnx/cat/command'
|
12
9
|
require 'pathname'
|
13
10
|
|
14
|
-
module
|
11
|
+
module Svnx
|
12
|
+
module IO
|
13
|
+
end
|
14
|
+
end
|
15
15
|
|
16
|
-
|
17
|
-
|
18
|
-
# which should exist).
|
16
|
+
# An element unites an svn element and a file/directory (at least one of
|
17
|
+
# which should exist).
|
19
18
|
|
20
|
-
|
21
|
-
|
19
|
+
class Svnx::IO::Element
|
20
|
+
include Logue::Loggable, Comparable
|
22
21
|
|
23
|
-
|
24
|
-
|
25
|
-
|
22
|
+
attr_reader :svn
|
23
|
+
attr_reader :path
|
24
|
+
attr_reader :local
|
25
|
+
|
26
|
+
def initialize args = Hash.new
|
27
|
+
info "args: #{args.inspect}".color("438802")
|
26
28
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
# svnurl = args[:svnurl]
|
31
|
-
# fname = args[:filename] || args[:file] # legacy
|
32
|
-
# $$$ todo: map svnurl to SVNElement, and fname to FSElement
|
33
|
-
|
34
|
-
@svn = args[:svn] # || (args[:file] && SVNElement.new(:filename => args[:file]))
|
35
|
-
@local = args[:local] && Pathname.new(args[:local]) # && PVN::FSElement.new(args[:local] || args[:file])
|
36
|
-
@path = args[:path]
|
37
|
-
|
38
|
-
info "local: #{@local.inspect}"
|
39
|
-
end
|
29
|
+
# svnurl = args[:svnurl]
|
30
|
+
# fname = args[:filename] || args[:file] # legacy
|
31
|
+
# $$$ todo: map svnurl to SVNElement, and fname to FSElement
|
40
32
|
|
41
|
-
|
42
|
-
|
43
|
-
|
33
|
+
@svn = args[:svn] # || (args[:file] && SVNElement.new(:filename => args[:file]))
|
34
|
+
@local = args[:local] && Pathname.new(args[:local]) # && PVN::FSElement.new(args[:local] || args[:file])
|
35
|
+
@path = args[:path]
|
36
|
+
|
37
|
+
info "local: #{@local.inspect}"
|
38
|
+
end
|
44
39
|
|
45
|
-
|
46
|
-
|
47
|
-
|
40
|
+
def exist?
|
41
|
+
@local && @local.exist?
|
42
|
+
end
|
48
43
|
|
49
|
-
|
50
|
-
|
51
|
-
|
44
|
+
def directory?
|
45
|
+
@local && @local.directory?
|
46
|
+
end
|
52
47
|
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
48
|
+
def file?
|
49
|
+
@local && @local.file?
|
50
|
+
end
|
51
|
+
|
52
|
+
def get_info revision = nil
|
53
|
+
return nil unless in_svn?
|
54
|
+
|
55
|
+
usepath = @local ? @local.to_path : @path
|
56
|
+
inf = Svnx::Info::Command.new url: usepath, revision: revision
|
57
|
+
inf.entry
|
58
|
+
end
|
60
59
|
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
end
|
60
|
+
def in_svn?
|
61
|
+
# svn status can only be a local path:
|
62
|
+
if @local
|
63
|
+
st = Svnx::StatusExec.new path: @local.to_path
|
64
|
+
st.entries.size == 0 || st.entries[0].status.to_s != 'unversioned'
|
65
|
+
else
|
66
|
+
raise "cannot determine svn status without a local path; only target '#{@path}' defined"
|
69
67
|
end
|
68
|
+
end
|
70
69
|
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
end
|
70
|
+
def find_entries args = Hash.new
|
71
|
+
revision = args[:revision]
|
72
|
+
status = args[:status]
|
73
|
+
|
74
|
+
if revision.nil?
|
75
|
+
find_by_status status
|
76
|
+
else
|
77
|
+
find_in_log revision, status
|
80
78
|
end
|
79
|
+
end
|
81
80
|
|
82
|
-
|
83
|
-
|
81
|
+
def find_in_log revision, action
|
82
|
+
svninfo = get_info
|
84
83
|
|
85
|
-
|
86
|
-
|
84
|
+
filter = svninfo.url.dup
|
85
|
+
filter.slice! svninfo.root
|
87
86
|
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
87
|
+
# we can't cache this, because we don't know if there has been an svn
|
88
|
+
# update since the previous run:
|
89
|
+
logexec = Svnx::LogExec.new path: @local, revision: revision, verbose: true, use_cache: false
|
90
|
+
entries = logexec.entries
|
91
|
+
|
92
|
+
act = action.kind_of?(Svnx::Action) ? action : Svnx::Action.new(action)
|
93
|
+
entries.match act, filter
|
94
|
+
end
|
96
95
|
|
97
|
-
|
98
|
-
|
99
|
-
|
96
|
+
def find_by_status status
|
97
|
+
statexec = Svnx::StatusExec.new path: @local, use_cache: false
|
98
|
+
entries = statexec.entries
|
100
99
|
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
100
|
+
entries.select do |entry|
|
101
|
+
status.nil? || entry.status.to_s == status.to_s
|
102
|
+
end.sort
|
103
|
+
end
|
105
104
|
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
105
|
+
def log_entries args = Hash.new
|
106
|
+
rev = args[:revision]
|
107
|
+
# use_cache should be conditional on revision:
|
108
|
+
logexec = Svnx::LogExec.new :path => @local, :revision => rev && rev.to_s, :verbose => true, :use_cache => false
|
109
|
+
logexec.entries
|
110
|
+
end
|
112
111
|
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
112
|
+
def cat args = Hash.new
|
113
|
+
rev = args[:revision]
|
114
|
+
catexec = Svnx::CatExec.new :path => @local, :revision => rev && rev.to_s, :use_cache => false
|
115
|
+
catexec.output
|
116
|
+
end
|
118
117
|
|
119
|
-
|
120
|
-
|
121
|
-
|
118
|
+
def to_s
|
119
|
+
"svn => " + @svn.to_s + "; local => " + @local.to_s
|
120
|
+
end
|
122
121
|
|
123
|
-
|
124
|
-
|
125
|
-
end
|
122
|
+
def <=> other
|
123
|
+
@local <=> other.local
|
126
124
|
end
|
127
125
|
end
|