cir 0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE.txt +202 -0
- data/Rakefile +25 -0
- data/bin/cir +19 -0
- data/lib/cir.rb +32 -0
- data/lib/cir/cli/command.rb +41 -0
- data/lib/cir/cli/command_with_repository.rb +33 -0
- data/lib/cir/cli/deregister_command.rb +35 -0
- data/lib/cir/cli/init_command.rb +31 -0
- data/lib/cir/cli/main.rb +95 -0
- data/lib/cir/cli/register_command.rb +35 -0
- data/lib/cir/cli/restore_command.rb +34 -0
- data/lib/cir/cli/status_command.rb +43 -0
- data/lib/cir/cli/update_command.rb +35 -0
- data/lib/cir/diff_manager.rb +52 -0
- data/lib/cir/exception/exceptions.rb +28 -0
- data/lib/cir/git_repository.rb +96 -0
- data/lib/cir/repository.rb +209 -0
- data/lib/cir/stored_file.rb +41 -0
- data/lib/cir/version.rb +17 -0
- data/test/cir_test_case.rb +81 -0
- data/test/test_diff_manager.rb +32 -0
- data/test/test_git_repository.rb +88 -0
- data/test/test_repository.rb +163 -0
- data/test/test_stored_file.rb +23 -0
- metadata +138 -0
@@ -0,0 +1,41 @@
|
|
1
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
2
|
+
# you may not use this file except in compliance with the License.
|
3
|
+
# You may obtain a copy of the License at
|
4
|
+
#
|
5
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
6
|
+
#
|
7
|
+
# Unless required by applicable law or agreed to in writing, software
|
8
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
9
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
10
|
+
# See the License for the specific language governing permissions and
|
11
|
+
# limitations under the License.
|
12
|
+
#
|
13
|
+
|
14
|
+
module Cir
|
15
|
+
##
|
16
|
+
# Represents metadata about stored file.
|
17
|
+
class StoredFile
|
18
|
+
|
19
|
+
##
|
20
|
+
# Full file path of the original file location
|
21
|
+
attr :file_path
|
22
|
+
|
23
|
+
##
|
24
|
+
# Location in the repository with stored and versioned copy of the file
|
25
|
+
attr :repository_location
|
26
|
+
|
27
|
+
##
|
28
|
+
# Constructor that will optionally populate attributes
|
29
|
+
def initialize(attrs = {})
|
30
|
+
attrs.each do |attr, value|
|
31
|
+
instance_variable_set "@#{attr}", value
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
##
|
36
|
+
# Generate diff using DiffManager
|
37
|
+
def diff
|
38
|
+
Cir::DiffManager.create(repository_location, file_path)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
data/lib/cir/version.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
2
|
+
# you may not use this file except in compliance with the License.
|
3
|
+
# You may obtain a copy of the License at
|
4
|
+
#
|
5
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
6
|
+
#
|
7
|
+
# Unless required by applicable law or agreed to in writing, software
|
8
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
9
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
10
|
+
# See the License for the specific language governing permissions and
|
11
|
+
# limitations under the License.
|
12
|
+
#
|
13
|
+
module Cir
|
14
|
+
##
|
15
|
+
# Version of Cir
|
16
|
+
VERSION = "0.1"
|
17
|
+
end # module Cir
|
@@ -0,0 +1,81 @@
|
|
1
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
2
|
+
# you may not use this file except in compliance with the License.
|
3
|
+
# You may obtain a copy of the License at
|
4
|
+
#
|
5
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
6
|
+
#
|
7
|
+
# Unless required by applicable law or agreed to in writing, software
|
8
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
9
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
10
|
+
# See the License for the specific language governing permissions and
|
11
|
+
# limitations under the License.
|
12
|
+
#
|
13
|
+
require 'cir'
|
14
|
+
require 'tmpdir'
|
15
|
+
require 'test/unit'
|
16
|
+
require 'fileutils'
|
17
|
+
|
18
|
+
##
|
19
|
+
# Parent test case that will contain shared functionality that we need
|
20
|
+
# across various test cases.
|
21
|
+
class CirTestCase < Test::Unit::TestCase
|
22
|
+
|
23
|
+
##
|
24
|
+
# Prepare each test, currently:
|
25
|
+
# * Forward stderr and stdout to /dev/null
|
26
|
+
# * Prepare working directory (in tmp space)
|
27
|
+
def setup
|
28
|
+
# Create working directory
|
29
|
+
@workDir = Dir.mktmpdir(["cir_test_", "_#{self.class.name}"])
|
30
|
+
@repoDir = "#{@workDir}/repo"
|
31
|
+
|
32
|
+
# Forward stderr/stdout to /dev/null to not mess with test output
|
33
|
+
@original_stderr = $stderr
|
34
|
+
@original_stdout = $stdout
|
35
|
+
$stderr = File.open(File::NULL, "w")
|
36
|
+
$stdout = File.open(File::NULL, "w")
|
37
|
+
end
|
38
|
+
|
39
|
+
##
|
40
|
+
# Undo all the changes we did in #setup
|
41
|
+
def teardown
|
42
|
+
# Remove forwarding of stderr/stdout to /dev/null
|
43
|
+
$stderr = @original_stderr
|
44
|
+
$stdout = @original_stdout
|
45
|
+
|
46
|
+
# Cleaning up working directory
|
47
|
+
FileUtils.rm_rf(@workDir, secure: true)
|
48
|
+
end
|
49
|
+
|
50
|
+
##
|
51
|
+
# Create new file with given file name inside the work directory
|
52
|
+
# and return absolute path to the created file.
|
53
|
+
def create_file(fileName, content)
|
54
|
+
full_path = "#{@workDir}/#{fileName}"
|
55
|
+
File.open(full_path, 'w') { |f| f.write(content) }
|
56
|
+
File.expand_path(full_path)
|
57
|
+
end
|
58
|
+
|
59
|
+
##
|
60
|
+
# Initialize Cir::Repository inside @repoDir and persist that inside
|
61
|
+
# @repo variable (e.g. we have max 1 repo per test instance).
|
62
|
+
def init_repo
|
63
|
+
Cir::Repository.create(@repoDir)
|
64
|
+
@repo = Cir::Repository.new(@repoDir)
|
65
|
+
end
|
66
|
+
|
67
|
+
##
|
68
|
+
# Initialize only git repository (no metadata) and persist that inside
|
69
|
+
# @repo variable.
|
70
|
+
def init_git_repo
|
71
|
+
@repo = Cir::GitRepository.create(@repoDir)
|
72
|
+
end
|
73
|
+
|
74
|
+
##
|
75
|
+
# Asserts if given file have been correctly updated in the git working
|
76
|
+
# directory.
|
77
|
+
def assert_file_in_repo(file)
|
78
|
+
diff = Cir::DiffManager.create(file, "#{@repDir}/#{file}")
|
79
|
+
assert_false diff.changed?
|
80
|
+
end
|
81
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
2
|
+
# you may not use this file except in compliance with the License.
|
3
|
+
# You may obtain a copy of the License at
|
4
|
+
#
|
5
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
6
|
+
#
|
7
|
+
# Unless required by applicable law or agreed to in writing, software
|
8
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
9
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
10
|
+
# See the License for the specific language governing permissions and
|
11
|
+
# limitations under the License.
|
12
|
+
#
|
13
|
+
require 'cir_test_case'
|
14
|
+
|
15
|
+
class DiffManagerTest < CirTestCase
|
16
|
+
|
17
|
+
def test_create
|
18
|
+
# Test files
|
19
|
+
file_a = create_file("a.file", "A")
|
20
|
+
file_b = create_file("b.file", "A")
|
21
|
+
file_c = create_file("c.file", "B")
|
22
|
+
|
23
|
+
# Same content
|
24
|
+
diff = Cir::DiffManager.create(file_a, file_b)
|
25
|
+
assert_false diff.changed?
|
26
|
+
|
27
|
+
# Different content
|
28
|
+
diff = Cir::DiffManager.create(file_a, file_c)
|
29
|
+
assert diff.changed?
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
@@ -0,0 +1,88 @@
|
|
1
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
2
|
+
# you may not use this file except in compliance with the License.
|
3
|
+
# You may obtain a copy of the License at
|
4
|
+
#
|
5
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
6
|
+
#
|
7
|
+
# Unless required by applicable law or agreed to in writing, software
|
8
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
9
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
10
|
+
# See the License for the specific language governing permissions and
|
11
|
+
# limitations under the License.
|
12
|
+
#
|
13
|
+
require 'tmpdir'
|
14
|
+
require 'cir_test_case'
|
15
|
+
|
16
|
+
class GitRepositoryTest < CirTestCase
|
17
|
+
|
18
|
+
def test_create_already_exists
|
19
|
+
assert_raise Cir::Exception::RepositoryExists do
|
20
|
+
Cir::GitRepository.create(@workDir)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def test_create
|
25
|
+
Cir::GitRepository.create(@repoDir)
|
26
|
+
assert Dir.exists? "#{@repoDir}/.git"
|
27
|
+
end
|
28
|
+
|
29
|
+
def test_add_file_and_commit
|
30
|
+
init_git_repo
|
31
|
+
|
32
|
+
create_file("repo/a.file", "Content")
|
33
|
+
create_file("repo/b.file", "Content")
|
34
|
+
|
35
|
+
@repo.add_file "a.file"
|
36
|
+
@repo.add_file "b.file"
|
37
|
+
@repo.commit
|
38
|
+
|
39
|
+
ruggedRepo = Rugged::Repository.new(@repoDir)
|
40
|
+
master = ruggedRepo.branches.first
|
41
|
+
assert_equal "master", master.name
|
42
|
+
assert_not_nil master.target
|
43
|
+
|
44
|
+
assert_match "a.file", master.target.message
|
45
|
+
assert_match "b.file", master.target.message
|
46
|
+
|
47
|
+
tree = master.target.tree
|
48
|
+
assert_not_nil tree
|
49
|
+
assert_equal 2, tree.count
|
50
|
+
assert_not_nil tree['a.file']
|
51
|
+
assert_not_nil tree['b.file']
|
52
|
+
end
|
53
|
+
|
54
|
+
def test_remove_file_and_commit
|
55
|
+
init_git_repo
|
56
|
+
|
57
|
+
ruggedRepo = Rugged::Repository.new(@repoDir)
|
58
|
+
|
59
|
+
create_file("repo/a.file", "Content")
|
60
|
+
@repo.add_file "a.file"
|
61
|
+
@repo.commit
|
62
|
+
assert_equal 1, ruggedRepo.branches.first.target.tree.count
|
63
|
+
|
64
|
+
@repo.remove_file("a.file")
|
65
|
+
@repo.commit
|
66
|
+
assert_equal 0, ruggedRepo.branches.first.target.tree.count
|
67
|
+
end
|
68
|
+
|
69
|
+
def test_commit_message
|
70
|
+
init_git_repo
|
71
|
+
|
72
|
+
ruggedRepo = Rugged::Repository.new(@repoDir)
|
73
|
+
|
74
|
+
# Default commit message starts with "Affected files"
|
75
|
+
create_file("repo/a.file", "Content")
|
76
|
+
@repo.add_file "a.file"
|
77
|
+
@repo.commit
|
78
|
+
assert_match "Affected files", ruggedRepo.branches.first.target.message
|
79
|
+
|
80
|
+
# Which can be overridden to arbitrary text
|
81
|
+
@repo.remove_file "a.file"
|
82
|
+
@repo.commit("My message")
|
83
|
+
assert_match "My message", ruggedRepo.branches.first.target.message
|
84
|
+
end
|
85
|
+
|
86
|
+
|
87
|
+
end
|
88
|
+
|
@@ -0,0 +1,163 @@
|
|
1
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
2
|
+
# you may not use this file except in compliance with the License.
|
3
|
+
# You may obtain a copy of the License at
|
4
|
+
#
|
5
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
6
|
+
#
|
7
|
+
# Unless required by applicable law or agreed to in writing, software
|
8
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
9
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
10
|
+
# See the License for the specific language governing permissions and
|
11
|
+
# limitations under the License.
|
12
|
+
#
|
13
|
+
require 'tmpdir'
|
14
|
+
require 'cir_test_case'
|
15
|
+
|
16
|
+
class RepositoryTest < CirTestCase
|
17
|
+
|
18
|
+
def test_create_already_exists
|
19
|
+
assert_raise Cir::Exception::RepositoryExists do
|
20
|
+
Cir::Repository.create(@workDir)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def test_create
|
25
|
+
init_repo
|
26
|
+
|
27
|
+
fileList = "#{@repoDir}/cir.file_list.yml"
|
28
|
+
|
29
|
+
assert File.exists? fileList
|
30
|
+
yaml = YAML::Store.new(fileList)
|
31
|
+
|
32
|
+
assert_equal(1, yaml.transaction { yaml[:version] })
|
33
|
+
assert_equal({}, yaml.transaction { yaml[:files] })
|
34
|
+
end
|
35
|
+
|
36
|
+
|
37
|
+
def test_register
|
38
|
+
init_repo
|
39
|
+
|
40
|
+
# Prepare test file
|
41
|
+
test_file = create_file("A", "Input data")
|
42
|
+
|
43
|
+
# Register in repository - we'll use not a final path to make sure that repository will correctly resolve it
|
44
|
+
@repo.register ["#{File.dirname(test_file)}/./#{File.basename(test_file)}"]
|
45
|
+
|
46
|
+
# Which should create entity in the repository
|
47
|
+
yaml = YAML::Store.new(@repoDir + '/cir.file_list.yml')
|
48
|
+
result = yaml.transaction { yaml[:files][test_file] }
|
49
|
+
assert_not_nil result
|
50
|
+
assert_equal({}, result)
|
51
|
+
|
52
|
+
# And the file should also exists in the working directory
|
53
|
+
assert File.exists?("#{@repoDir}/#{test_file}")
|
54
|
+
|
55
|
+
# Registering again should fail
|
56
|
+
assert_raise Cir::Exception::AlreadyRegistered do
|
57
|
+
@repo.register [test_file]
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def test_registered
|
62
|
+
init_repo
|
63
|
+
|
64
|
+
test_file = create_file("A", "Input data")
|
65
|
+
|
66
|
+
@repo.register [test_file]
|
67
|
+
|
68
|
+
assert @repo.registered?(test_file)
|
69
|
+
assert_false @repo.registered?("/blah")
|
70
|
+
end
|
71
|
+
|
72
|
+
def test_deregister
|
73
|
+
init_repo
|
74
|
+
|
75
|
+
# Prepare test file
|
76
|
+
test_file = create_file("A", "Input data")
|
77
|
+
|
78
|
+
# Register in repository
|
79
|
+
@repo.register [test_file]
|
80
|
+
assert @repo.registered? test_file
|
81
|
+
|
82
|
+
# Deregister the file now
|
83
|
+
@repo.deregister [test_file]
|
84
|
+
|
85
|
+
assert_false @repo.registered? test_file
|
86
|
+
assert_false File.exists?("#{@repoDir}/#{test_file}")
|
87
|
+
|
88
|
+
# Deregister of not registered file should raise an exception
|
89
|
+
assert_raise(Cir::Exception::NotRegistered) { @repo.deregister ["X"]}
|
90
|
+
end
|
91
|
+
|
92
|
+
def test_status
|
93
|
+
init_repo
|
94
|
+
|
95
|
+
test_file_a = create_file("A", "data")
|
96
|
+
test_file_b = create_file("B", "data")
|
97
|
+
@repo.register [test_file_a, test_file_b]
|
98
|
+
|
99
|
+
# Everything
|
100
|
+
status = @repo.status
|
101
|
+
assert_not_nil status
|
102
|
+
assert_equal status.size, 2
|
103
|
+
|
104
|
+
# Not registered file
|
105
|
+
assert_raise(Cir::Exception::NotRegistered) { @repo.status ["X"] }
|
106
|
+
|
107
|
+
# One specific file
|
108
|
+
status = @repo.status [test_file_a]
|
109
|
+
assert_not_nil status
|
110
|
+
assert_equal status.size, 1
|
111
|
+
end
|
112
|
+
|
113
|
+
def test_update
|
114
|
+
init_repo
|
115
|
+
|
116
|
+
test_file = create_file("A", "data")
|
117
|
+
@repo.register [test_file]
|
118
|
+
|
119
|
+
# Update non existing file
|
120
|
+
assert_raise(Cir::Exception::NotRegistered) { @repo.update ["X"] }
|
121
|
+
|
122
|
+
# Updating via "all"
|
123
|
+
create_file("A", "New data")
|
124
|
+
@repo.update
|
125
|
+
assert_file_in_repo test_file
|
126
|
+
|
127
|
+
# Updating via "given file"
|
128
|
+
create_file("A", "Newer data")
|
129
|
+
@repo.update
|
130
|
+
assert_file_in_repo test_file
|
131
|
+
end
|
132
|
+
|
133
|
+
def test_restore
|
134
|
+
init_repo
|
135
|
+
|
136
|
+
test_file = create_file("A", "data")
|
137
|
+
@repo.register [test_file]
|
138
|
+
|
139
|
+
# Restore non existing file
|
140
|
+
assert_raise(Cir::Exception::NotRegistered) { @repo.restore ["X"] }
|
141
|
+
|
142
|
+
# Restoring non-existing file via "all"
|
143
|
+
FileUtils.rm test_file
|
144
|
+
@repo.restore
|
145
|
+
assert_file_in_repo test_file
|
146
|
+
|
147
|
+
# Restore non-existing file specifically by file name
|
148
|
+
FileUtils.rm test_file
|
149
|
+
@repo.restore([test_file])
|
150
|
+
assert_file_in_repo test_file
|
151
|
+
|
152
|
+
# Restoring via "all"
|
153
|
+
create_file("A", "New data")
|
154
|
+
@repo.restore(nil, true)
|
155
|
+
assert_file_in_repo test_file
|
156
|
+
|
157
|
+
# Restore given file
|
158
|
+
create_file("A", "Newer data")
|
159
|
+
@repo.restore([test_file])
|
160
|
+
assert_file_in_repo test_file
|
161
|
+
end
|
162
|
+
|
163
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
2
|
+
# you may not use this file except in compliance with the License.
|
3
|
+
# You may obtain a copy of the License at
|
4
|
+
#
|
5
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
6
|
+
#
|
7
|
+
# Unless required by applicable law or agreed to in writing, software
|
8
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
9
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
10
|
+
# See the License for the specific language governing permissions and
|
11
|
+
# limitations under the License.
|
12
|
+
#
|
13
|
+
require 'cir_test_case'
|
14
|
+
|
15
|
+
class StoredFileTest < CirTestCase
|
16
|
+
|
17
|
+
def test_initialize
|
18
|
+
file = Cir::StoredFile.new file_path: "/home/jarcec/", repository_location: "location"
|
19
|
+
assert_equal file.file_path, "/home/jarcec/"
|
20
|
+
assert_equal file.repository_location, "location"
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|