perforce2svn 0.7.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.
- data/Gemfile +2 -0
- data/Gemfile.lock +38 -0
- data/LICENSE +23 -0
- data/README.markdown +66 -0
- data/Rakefile +24 -0
- data/bin/perforce2svn +11 -0
- data/lib/VERSION.yml +6 -0
- data/lib/perforce2svn/cli.rb +117 -0
- data/lib/perforce2svn/environment.rb +66 -0
- data/lib/perforce2svn/errors.rb +16 -0
- data/lib/perforce2svn/logging.rb +35 -0
- data/lib/perforce2svn/mapping/analyzer.rb +30 -0
- data/lib/perforce2svn/mapping/branch_mapping.rb +32 -0
- data/lib/perforce2svn/mapping/commands.rb +75 -0
- data/lib/perforce2svn/mapping/help.txt +139 -0
- data/lib/perforce2svn/mapping/lexer.rb +101 -0
- data/lib/perforce2svn/mapping/mapping_file.rb +65 -0
- data/lib/perforce2svn/mapping/operation.rb +8 -0
- data/lib/perforce2svn/mapping/parser.rb +145 -0
- data/lib/perforce2svn/migrator.rb +71 -0
- data/lib/perforce2svn/perforce/commit_builder.rb +159 -0
- data/lib/perforce2svn/perforce/p4_depot.rb +69 -0
- data/lib/perforce2svn/perforce/perforce_file.rb +81 -0
- data/lib/perforce2svn/subversion/svn_repo.rb +156 -0
- data/lib/perforce2svn/subversion/svn_transaction.rb +136 -0
- data/lib/perforce2svn/version_range.rb +43 -0
- data/mjt.map +7 -0
- data/perforce2svn.gemspec +49 -0
- data/spec/integration/hamlet.txt +7067 -0
- data/spec/integration/madmen_icon_bigger.jpg +0 -0
- data/spec/integration/perforce/p4_depot_spec.rb +16 -0
- data/spec/integration/perforce/perforce_file.yml +4 -0
- data/spec/integration/perforce/perforce_file_spec.rb +19 -0
- data/spec/integration/subversion/svn_repo_spec.rb +93 -0
- data/spec/integration/subversion/svn_transaction_spec.rb +112 -0
- data/spec/perforce2svn/cli_spec.rb +61 -0
- data/spec/perforce2svn/mapping/analyzer_spec.rb +41 -0
- data/spec/perforce2svn/mapping/branch_mapping_spec.rb +40 -0
- data/spec/perforce2svn/mapping/lexer_spec.rb +43 -0
- data/spec/perforce2svn/mapping/parser_spec.rb +140 -0
- data/spec/perforce2svn/perforce/commit_builder_spec.rb +74 -0
- data/spec/perforce2svn/version_range_spec.rb +42 -0
- data/spec/spec_helpers.rb +44 -0
- metadata +230 -0
Binary file
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'spec_helpers'
|
2
|
+
require 'perforce2svn/perforce/p4_depot'
|
3
|
+
|
4
|
+
module Perforce2Svn::Perforce
|
5
|
+
describe P4Depot do
|
6
|
+
it "should be able to connect to the Perforce server" do
|
7
|
+
attempting {
|
8
|
+
P4Depot.instance.connect!
|
9
|
+
}.should_not raise_error
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should be able to retrieve the latest revision" do
|
13
|
+
P4Depot.instance.latest_revision.should >= 8000
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'spec_helpers'
|
2
|
+
require 'perforce2svn/perforce/perforce_file'
|
3
|
+
require 'yaml'
|
4
|
+
|
5
|
+
module Perforce2Svn::Perforce
|
6
|
+
describe PerforceFile do
|
7
|
+
before :each do
|
8
|
+
config_file = File.join(File.dirname(__FILE__), 'perforce_file.yml')
|
9
|
+
@config = YAML::load_file(config_file)
|
10
|
+
@file = PerforceFile.new(@config['revision'], @config['path'], nil, 'text', 'add')
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should be able to retrieve file contents." do
|
14
|
+
@file.contents.should match(Regexp.compile(@config['match']))
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should locate the symlink"
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,93 @@
|
|
1
|
+
require 'perforce2svn/errors'
|
2
|
+
require 'perforce2svn/subversion/svn_repo'
|
3
|
+
require 'spec_helpers'
|
4
|
+
require 'fileutils'
|
5
|
+
|
6
|
+
module Perforce2Svn::Subversion
|
7
|
+
describe SvnRepo do
|
8
|
+
include CommitHelper
|
9
|
+
|
10
|
+
before :each do
|
11
|
+
@repo = SvnRepo.new('REPO')
|
12
|
+
end
|
13
|
+
|
14
|
+
after :each do
|
15
|
+
@repo.delete!
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'should create a new repository upon initialization' do
|
19
|
+
File.exists?(@repo.repository_path).should be(true)
|
20
|
+
File.exists?(File.join(@repo.repository_path, 'hooks')).should be(true)
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'should fail to create a transaction when a block is not given' do
|
24
|
+
attempting {
|
25
|
+
@repo.transaction('me', Time.now, 'log')
|
26
|
+
}.should raise_error(Perforce2Svn::SvnTransactionError, /block-scoped/)
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should be able to retrieve the file contents from a path" do
|
30
|
+
write('/a', "this is some text")
|
31
|
+
@repo.pull_contents('/a').should eql("this is some text")
|
32
|
+
end
|
33
|
+
|
34
|
+
it "should fail when the file contents don't exist" do
|
35
|
+
attempting {
|
36
|
+
@repo.pull_contents('/a')
|
37
|
+
}.should raise_error(Svn::Error::FsNotFound, /revision 0/)
|
38
|
+
end
|
39
|
+
|
40
|
+
it "should fail when a file exists but not at a given revision" do
|
41
|
+
write('/a', 'content')
|
42
|
+
attempting {
|
43
|
+
@repo.pull_contents('/a', 10)
|
44
|
+
}.should raise_error(Svn::Error::FsNoSuchRevision, /10/)
|
45
|
+
end
|
46
|
+
|
47
|
+
it "should be able to determine when a path doesn't exist" do
|
48
|
+
@repo.exists?('/a').should be_false
|
49
|
+
end
|
50
|
+
|
51
|
+
it "should be able to determine when a path exists" do
|
52
|
+
write('/a', 'contents')
|
53
|
+
@repo.exists?('/a').should be_true
|
54
|
+
end
|
55
|
+
|
56
|
+
it "should be able to retrieve the commit log" do
|
57
|
+
write('/a', 'contents')
|
58
|
+
commit = @repo.commit_log(1)
|
59
|
+
commit.author.should eql('gabe')
|
60
|
+
end
|
61
|
+
|
62
|
+
it "should be fail to retrieve the commit log on a bad revision" do
|
63
|
+
attempting {
|
64
|
+
@repo.commit_log(10)
|
65
|
+
}.should raise_error(Svn::Error::FsNoSuchRevision, /10/)
|
66
|
+
end
|
67
|
+
|
68
|
+
it "should be able to retrieve a property" do
|
69
|
+
write('/a', 'contents', true)
|
70
|
+
@repo.prop_get('/a', 'svn:mime-type', 1).should eql('application/octet-stream')
|
71
|
+
end
|
72
|
+
|
73
|
+
it "should be able to list child directories" do
|
74
|
+
write('/a', 'contents')
|
75
|
+
write('/b', 'contents')
|
76
|
+
@repo.children('/').should eql(['a', 'b'])
|
77
|
+
end
|
78
|
+
|
79
|
+
it "should not retrieve properties on non-existent paths" do
|
80
|
+
write('/a', 'contents')
|
81
|
+
attempting {
|
82
|
+
@repo.prop_get('/b', Svn::Core::PROP_REVISION_LOG)
|
83
|
+
}.should raise_error(Svn::Error::FsNotFound, /\/b/)
|
84
|
+
end
|
85
|
+
|
86
|
+
it "should fail to retrieve properties on a bad revision" do
|
87
|
+
write('/a', 'contents')
|
88
|
+
attempting {
|
89
|
+
@repo.prop_get('/a', Svn::Core::PROP_REVISION_AUTHOR, 5)
|
90
|
+
}.should raise_error(Svn::Error::FsNoSuchRevision, /5/)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
@@ -0,0 +1,112 @@
|
|
1
|
+
require 'perforce2svn/subversion/svn_repo'
|
2
|
+
require 'spec_helpers'
|
3
|
+
require 'stringio'
|
4
|
+
|
5
|
+
module Perforce2Svn::Subversion
|
6
|
+
describe SvnTransaction do
|
7
|
+
include CommitHelper
|
8
|
+
|
9
|
+
before :each do
|
10
|
+
@repo = SvnRepo.new('REPO')
|
11
|
+
end
|
12
|
+
|
13
|
+
after :each do
|
14
|
+
@repo.delete!
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should be able to commit a single change" do
|
18
|
+
write('/a.txt', "this is some text\nthat\goes here")
|
19
|
+
@repo.pull_contents('/a.txt').should eql("this is some text\nthat\goes here")
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should be able to retrieve the updated file contents" do
|
23
|
+
write("/a.txt", "first commit")
|
24
|
+
write("/a.txt", 'second commit')
|
25
|
+
@repo.pull_contents('/a.txt').should eql('second commit')
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should be able to delete a file" do
|
29
|
+
write('/a', 'conent')
|
30
|
+
delete('/a')
|
31
|
+
attempting {
|
32
|
+
@repo.pull_contents('/a')
|
33
|
+
}.should raise_error
|
34
|
+
end
|
35
|
+
|
36
|
+
it "can create multiple directories" do
|
37
|
+
@repo.exists?('/a/b/c').should be(false)
|
38
|
+
|
39
|
+
@repo.transaction('g', Time.new, 'l') do |txn|
|
40
|
+
txn.exists?('/a/b/c').should be(false)
|
41
|
+
txn.mkdir('/a/b/c')
|
42
|
+
end
|
43
|
+
|
44
|
+
@repo.exists?('/a/b/c').should be(true)
|
45
|
+
end
|
46
|
+
|
47
|
+
it "can delete all parent directories" do
|
48
|
+
write('/a/b/c/d.txt', 'some text')
|
49
|
+
write('/a/b.txt', 'other text')
|
50
|
+
delete('/a/b/c/d.txt')
|
51
|
+
|
52
|
+
@repo.exists?('/a/b/c').should be(false)
|
53
|
+
end
|
54
|
+
|
55
|
+
it "will write binary mime types correctly" do
|
56
|
+
jpg = read_in('spec/integration/madmen_icon_bigger.jpg', 'rb')
|
57
|
+
write('/a.jpg', jpg, true)
|
58
|
+
|
59
|
+
@repo.pull_contents('/a.jpg').should eql(jpg)
|
60
|
+
@repo.prop_get('/a.jpg', 'svn:mime-type').should eql('application/octet-stream')
|
61
|
+
end
|
62
|
+
|
63
|
+
it "will make sure that big files are retained correctly" do
|
64
|
+
hamlet = read_in('spec/integration/hamlet.txt')
|
65
|
+
write('/hamlet.txt', hamlet)
|
66
|
+
|
67
|
+
@repo.pull_contents('/hamlet.txt').should eql(hamlet)
|
68
|
+
end
|
69
|
+
|
70
|
+
it "will handle symlinks correctly" do
|
71
|
+
write("/src.txt", "some content")
|
72
|
+
symlink('./src.txt', '/b.txt')
|
73
|
+
|
74
|
+
@repo.pull_contents('/b.txt').should eql('link ./src.txt')
|
75
|
+
@repo.prop_get('/b.txt', 'svn:special').should eql('*')
|
76
|
+
end
|
77
|
+
|
78
|
+
it "will return the most recent revision number on commit" do
|
79
|
+
write('/a.txt', 'content').should eql(1)
|
80
|
+
end
|
81
|
+
|
82
|
+
it "will be able to find if a directory has children" do
|
83
|
+
write('/a/b.txt', 'content')
|
84
|
+
write('/a/c.txt', 'content')
|
85
|
+
@repo.transaction('gabe', Time.now, 'r') do |txn|
|
86
|
+
txn.has_children?('/a').should be(true)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
it "will be able to copy paths" do
|
91
|
+
write('/a.txt', 'content')
|
92
|
+
@repo.transaction('gabe', Time.now, 'r') do |txn|
|
93
|
+
txn.copy('/a.txt', '/b.txt')
|
94
|
+
end
|
95
|
+
|
96
|
+
@repo.exists?('/a.txt').should be_true
|
97
|
+
@repo.exists?('/b.txt').should be_true
|
98
|
+
@repo.pull_contents('/b.txt').should eql('content')
|
99
|
+
end
|
100
|
+
|
101
|
+
it "will be able to move paths" do
|
102
|
+
write('/a.txt', 'content')
|
103
|
+
@repo.transaction('gabe', Time.now, 'r') do |txn|
|
104
|
+
txn.move('/a.txt', '/b.txt')
|
105
|
+
end
|
106
|
+
|
107
|
+
@repo.exists?('/a.txt').should be_false
|
108
|
+
@repo.exists?('/b.txt').should be_true
|
109
|
+
@repo.pull_contents('/b.txt').should eql('content')
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'perforce2svn/cli'
|
2
|
+
require 'perforce2svn/errors'
|
3
|
+
require 'spec_helpers'
|
4
|
+
|
5
|
+
module Perforce2Svn
|
6
|
+
module CLIHelper
|
7
|
+
def parse(*args)
|
8
|
+
cli = CLI.new
|
9
|
+
args << '--repository'
|
10
|
+
args << 'here'
|
11
|
+
args << __FILE__
|
12
|
+
cli.parse!(args, true)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
describe CLI do
|
17
|
+
include CLIHelper
|
18
|
+
|
19
|
+
it "should be able to parse the debug flag correctly" do
|
20
|
+
parse("--debug")[:debug].should be(true)
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should be able to retrieve the repository path" do
|
24
|
+
parse('-r', 'some/path')[:repository].should eql('here')
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should be able to parse the live path" do
|
28
|
+
parse('-l', '/')[:live_path].should eql('/')
|
29
|
+
end
|
30
|
+
|
31
|
+
it "should be able to skip updates" do
|
32
|
+
parse('--skip-commands')[:skip_commands].should be(true)
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should be able to skip perforce" do
|
36
|
+
parse('--skip-perforce')[:skip_perforce].should be(true)
|
37
|
+
end
|
38
|
+
|
39
|
+
it "should be able to run the analysis only" do
|
40
|
+
parse('-a')[:analyze_only].should be(true)
|
41
|
+
end
|
42
|
+
|
43
|
+
describe "when validating the count format" do
|
44
|
+
it "should fail when the start revision is less than 1" do
|
45
|
+
attempting_to {
|
46
|
+
parse('-c', '0:4')
|
47
|
+
}.should raise_error(Choosy::ValidationError, /Minimum/)
|
48
|
+
end
|
49
|
+
|
50
|
+
it "should set -1 when given HEAD" do
|
51
|
+
parse('-c', '1:HEAD')[:changes].max.should eql(-1)
|
52
|
+
end
|
53
|
+
|
54
|
+
it "should fail when the end revision < 1" do
|
55
|
+
attempting_to {
|
56
|
+
parse('-c', '1:0')
|
57
|
+
}.should raise_error(Choosy::ValidationError, /Maximum/)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'perforce2svn/logging'
|
2
|
+
require 'perforce2svn/mapping/analyzer'
|
3
|
+
require 'perforce2svn/mapping/commands'
|
4
|
+
require 'ostruct'
|
5
|
+
|
6
|
+
module Perforce2Svn::Mapping
|
7
|
+
|
8
|
+
module AnalyzerHelper
|
9
|
+
def analyzing(*commands)
|
10
|
+
a = Analyzer.new(File.dirname(__FILE__))
|
11
|
+
a.check(commands)
|
12
|
+
end
|
13
|
+
|
14
|
+
def updater(file = nil)
|
15
|
+
file ||= __FILE__
|
16
|
+
tok = OpenStruct.new
|
17
|
+
tok.line_number = 1
|
18
|
+
Update.new(tok, nil, file)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
describe "Mapping analyzer" do
|
23
|
+
include AnalyzerHelper
|
24
|
+
|
25
|
+
it "should be able to test whether updated files exist" do
|
26
|
+
analyzing(updater).should be(true)
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should fail when updated files don't exist" do
|
30
|
+
analyzing(updater("nowhere")).should be(false)
|
31
|
+
end
|
32
|
+
|
33
|
+
it "should be able to check multiple files" do
|
34
|
+
analyzing(updater("nowhere")).should be(false)
|
35
|
+
end
|
36
|
+
|
37
|
+
it "should be able to check when a file has a relative path" do
|
38
|
+
analyzing(updater(File.basename(__FILE__))).should be(true)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'spec_helpers'
|
2
|
+
require 'perforce2svn/mapping/branch_mapping'
|
3
|
+
require 'ostruct'
|
4
|
+
|
5
|
+
module Perforce2Svn::Mapping
|
6
|
+
module BranchMappingHelper
|
7
|
+
def map(p4, svn)
|
8
|
+
tok = OpenStruct.new
|
9
|
+
tok.line_number = 1
|
10
|
+
BranchMapping.new(tok, p4, svn)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
describe "Branch Mappings" do
|
15
|
+
include BranchMappingHelper
|
16
|
+
|
17
|
+
it "should be able to determine when a path doesn't match" do
|
18
|
+
bm = map('//depot/path/', '/svn/path/here')
|
19
|
+
bm.matches_perforce_path?('//depot/not/here').should be(false)
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should be able to determine when a path doesn't match" do
|
23
|
+
bm = map('//depot/path/', '/svn/path/here')
|
24
|
+
bm.matches_perforce_path?('//depot/path/goes/here').should be(true)
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should be able to format the dotted P4 path" do
|
28
|
+
bm = map('//depot/path/', '/svn/path/here')
|
29
|
+
bm.p4_dotted.should eql('//depot/path/...')
|
30
|
+
end
|
31
|
+
|
32
|
+
it "should be able to translate funky path characters correctly for subversion" do
|
33
|
+
bf = map("//p/", "/o/")
|
34
|
+
bf.to_svn_path("//p/%40/a").should eql("/o/@/a")
|
35
|
+
bf.to_svn_path("//p/%23/a").should eql("/o/#/a")
|
36
|
+
bf.to_svn_path("//p/%2a/a").should eql("/o/*/a")
|
37
|
+
bf.to_svn_path("//p/%25/a").should eql("/o/%/a")
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'perforce2svn/mapping/lexer'
|
2
|
+
|
3
|
+
module Perforce2Svn
|
4
|
+
module Mapping
|
5
|
+
|
6
|
+
describe "Mapping lexer" do
|
7
|
+
it "should be able to parse a set of simple tokens in a line" do
|
8
|
+
lexer = Lexer.new(nil)
|
9
|
+
tok = lexer.tokenize('migrate this/that other/file')
|
10
|
+
tok.length.should eql(3)
|
11
|
+
tok[0].should eql('migrate')
|
12
|
+
tok[1].should eql('this/that')
|
13
|
+
tok[2].should eql('other/file')
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should handle spaces in the path names" do
|
17
|
+
lexer = Lexer.new(nil)
|
18
|
+
tok = lexer.tokenize("migrate this/that\\ other/path will\\ be/something")
|
19
|
+
tok.length.should eql(3)
|
20
|
+
tok[0].should eql('migrate')
|
21
|
+
tok[1].should eql("this/that other/path")
|
22
|
+
tok[2].should eql("will be/something")
|
23
|
+
end
|
24
|
+
|
25
|
+
it "will delete multiple spaces" do
|
26
|
+
lexer = Lexer.new(nil)
|
27
|
+
tok = lexer.tokenize(" migrate this/that and/a\\ nother ");
|
28
|
+
tok.length.should eql(3)
|
29
|
+
tok[0].should eql('migrate')
|
30
|
+
tok[1].should eql('this/that')
|
31
|
+
tok[2].should eql('and/a nother')
|
32
|
+
end
|
33
|
+
|
34
|
+
it "should leave off the comments at the end of lines" do
|
35
|
+
lexer = Lexer.new(nil)
|
36
|
+
tok = lexer.tokenize("this is a # comment string")
|
37
|
+
tok.length.should eql(3)
|
38
|
+
tok[0].should eql('this')
|
39
|
+
tok[2].should eql('a')
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,140 @@
|
|
1
|
+
require 'perforce2svn/mapping/parser'
|
2
|
+
require 'stringio'
|
3
|
+
|
4
|
+
module Perforce2Svn::Mapping
|
5
|
+
module ParserHelper
|
6
|
+
def parse(txt)
|
7
|
+
p = Parser.new
|
8
|
+
p.parse!(StringIO.new(txt), 'live')
|
9
|
+
end
|
10
|
+
|
11
|
+
def mappings(txt)
|
12
|
+
parse(txt)[:mappings]
|
13
|
+
end
|
14
|
+
|
15
|
+
def commands(txt)
|
16
|
+
parse(txt)[:commands]
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
describe Parser do
|
21
|
+
include ParserHelper
|
22
|
+
|
23
|
+
it "should fail when an unknown directive is found" do
|
24
|
+
parse(<<EOF
|
25
|
+
# A comment
|
26
|
+
not-directive arg
|
27
|
+
EOF
|
28
|
+
)[:failed].should be(true)
|
29
|
+
end
|
30
|
+
|
31
|
+
it "should be able to parse 'update's" do
|
32
|
+
parse("update /some/path")[:failed].should be(false)
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should be able to parse 'migrate'" do
|
36
|
+
c = mappings("migrate //depot/path /svn/path")
|
37
|
+
c[0].class.should eql(BranchMapping)
|
38
|
+
c[0].line_number.should eql(1)
|
39
|
+
c[0].svn_path.should eql('/svn/path/')
|
40
|
+
end
|
41
|
+
|
42
|
+
it "should fail to parse the 'update' command without a svn prefix" do
|
43
|
+
parse("update src/main/pom.xml")[:failed].should be(true)
|
44
|
+
end
|
45
|
+
|
46
|
+
it "should parse the 'update' command when an svn prefix is available" do
|
47
|
+
parse(<<EOF
|
48
|
+
svn-prefix /some/path
|
49
|
+
update src/main/pom.xml
|
50
|
+
EOF
|
51
|
+
)[:failed].should be(false)
|
52
|
+
end
|
53
|
+
|
54
|
+
it "should parse the mapping file and return a list of migrations" do
|
55
|
+
m = mappings(<<EOF
|
56
|
+
migrate //depot/path /trunk/project
|
57
|
+
svn-prefix /trunk
|
58
|
+
migrate //depot/partition another-project
|
59
|
+
EOF
|
60
|
+
)
|
61
|
+
|
62
|
+
first = m[0]
|
63
|
+
first.line_number.should eql(1)
|
64
|
+
first.p4_path.should eql('//depot/path/')
|
65
|
+
first.svn_path.should eql('/trunk/project/')
|
66
|
+
|
67
|
+
second = m[1]
|
68
|
+
second.line_number.should eql(3)
|
69
|
+
second.p4_path.should eql('//depot/partition/')
|
70
|
+
second.svn_path.should eql('/trunk/another-project/')
|
71
|
+
end
|
72
|
+
|
73
|
+
it "should be able to correctly parse updates" do
|
74
|
+
update = commands("update /src/dest.xml")[0]
|
75
|
+
update.class.should eql(Update)
|
76
|
+
update.line_number.should eql(1)
|
77
|
+
update.live_path.should eql('live/src/dest.xml')
|
78
|
+
update.svn_path.should eql('/src/dest.xml')
|
79
|
+
end
|
80
|
+
|
81
|
+
it "should be able to correctly parse delete" do
|
82
|
+
delete = commands("delete /src/another.java")[0]
|
83
|
+
delete.class.should eql(Delete)
|
84
|
+
delete.line_number.should eql(1)
|
85
|
+
delete.svn_path.should eql('/src/another.java')
|
86
|
+
end
|
87
|
+
|
88
|
+
it "should be able to correctly parse moves" do
|
89
|
+
move = commands("move /this/location.txt /to/here/location.txt")[0]
|
90
|
+
move.class.should eql(Move)
|
91
|
+
move.line_number.should eql(1)
|
92
|
+
move.svn_from.should eql('/this/location.txt')
|
93
|
+
move.svn_to.should eql('/to/here/location.txt')
|
94
|
+
end
|
95
|
+
|
96
|
+
it "should be able to correctly parse copies" do
|
97
|
+
copy = commands("copy /src.txt /dest.txt")[0]
|
98
|
+
copy.class.should eql(Copy)
|
99
|
+
copy.line_number.should eql(1)
|
100
|
+
copy.svn_from.should eql('/src.txt')
|
101
|
+
copy.svn_to.should eql('/dest.txt')
|
102
|
+
end
|
103
|
+
|
104
|
+
it "should be able to insert the svn prefix when a live path is calculated" do
|
105
|
+
update = commands("svn-prefix /trunk/project\nupdate src/dest.xml")[0]
|
106
|
+
update.live_path.should eql('live/trunk/project/src/dest.xml')
|
107
|
+
update.svn_path.should eql('/trunk/project/src/dest.xml')
|
108
|
+
end
|
109
|
+
|
110
|
+
it "should fail when too many arguments are given to a command" do
|
111
|
+
parse('update /this/path /should/not/be')[:failed].should be(true)
|
112
|
+
end
|
113
|
+
|
114
|
+
it "should add the author to the context" do
|
115
|
+
parse('author An author')[:author].should eql('An author')
|
116
|
+
end
|
117
|
+
|
118
|
+
it "should add the message to the context" do
|
119
|
+
parse(<<EOF
|
120
|
+
message this is a message that \
|
121
|
+
should span multiple lines \
|
122
|
+
and continue
|
123
|
+
EOF
|
124
|
+
)[:message].should eql('this is a message that should span multiple lines and continue')
|
125
|
+
end
|
126
|
+
|
127
|
+
it "should be able to order the commands" do
|
128
|
+
cmds = commands(<<EOF
|
129
|
+
update /src/dest.xml
|
130
|
+
delete /src/another.java
|
131
|
+
EOF
|
132
|
+
)
|
133
|
+
|
134
|
+
cmds[0].class.should eql(Update)
|
135
|
+
cmds[0].line_number.should eql(1)
|
136
|
+
cmds[1].class.should eql(Delete)
|
137
|
+
cmds[1].line_number.should eql(2)
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|