store_agent 1.0.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.
- checksums.yaml +7 -0
- data/.gitignore +14 -0
- data/.rspec +3 -0
- data/Gemfile +4 -0
- data/Guardfile +5 -0
- data/LICENSE +202 -0
- data/README.md +433 -0
- data/Rakefile +2 -0
- data/lib/store_agent.rb +31 -0
- data/lib/store_agent/config.rb +152 -0
- data/lib/store_agent/data_encoder.rb +32 -0
- data/lib/store_agent/data_encoder/gzip_encoder.rb +50 -0
- data/lib/store_agent/data_encoder/openssl_aes_256_cbc_encoder.rb +65 -0
- data/lib/store_agent/exceptions.rb +87 -0
- data/lib/store_agent/node.rb +26 -0
- data/lib/store_agent/node/attachment.rb +93 -0
- data/lib/store_agent/node/attachment/metadata.rb +120 -0
- data/lib/store_agent/node/attachment/permission.rb +121 -0
- data/lib/store_agent/node/object.rb +233 -0
- data/lib/store_agent/node/object/directory_object.rb +264 -0
- data/lib/store_agent/node/object/file_object.rb +197 -0
- data/lib/store_agent/node/object/virtual_object.rb +25 -0
- data/lib/store_agent/node/prepend_module/locker.rb +125 -0
- data/lib/store_agent/node/prepend_module/path_validator.rb +138 -0
- data/lib/store_agent/node/prepend_module/permission_checker.rb +96 -0
- data/lib/store_agent/user.rb +111 -0
- data/lib/store_agent/validator.rb +60 -0
- data/lib/store_agent/version.rb +19 -0
- data/lib/store_agent/version_manager.rb +101 -0
- data/lib/store_agent/version_manager/ruby_git.rb +100 -0
- data/lib/store_agent/version_manager/rugged_git.rb +133 -0
- data/lib/store_agent/workspace.rb +88 -0
- data/spec/spec_helper.rb +47 -0
- data/spec/store_agent/data_encoder/encoder_shared_context.rb +74 -0
- data/spec/store_agent/data_encoder/gzip_encoder_spec.rb +41 -0
- data/spec/store_agent/data_encoder/openssl_aes_256_cbc_encoder_spec.rb +42 -0
- data/spec/store_agent/data_encoder_spec.rb +78 -0
- data/spec/store_agent/node/directory_object_spec.rb +563 -0
- data/spec/store_agent/node/file_object_spec.rb +379 -0
- data/spec/store_agent/node/locker_spec.rb +191 -0
- data/spec/store_agent/node/metadata_spec.rb +339 -0
- data/spec/store_agent/node/object_spec.rb +73 -0
- data/spec/store_agent/node/path_validator_spec.rb +121 -0
- data/spec/store_agent/node/permission_spec.rb +232 -0
- data/spec/store_agent/user_spec.rb +127 -0
- data/spec/store_agent/version_manager/git_shared_context.rb +286 -0
- data/spec/store_agent/version_manager/ruby_git_spec.rb +32 -0
- data/spec/store_agent/version_manager/rugged_git_spec.rb +32 -0
- data/spec/store_agent/workspace_spec.rb +107 -0
- data/spec/store_agent_spec.rb +53 -0
- data/store_agent.gemspec +33 -0
- metadata +252 -0
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
#--
|
|
2
|
+
# Copyright 2015 realglobe, Inc.
|
|
3
|
+
#
|
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
# you may not use this file except in compliance with the License.
|
|
6
|
+
# You may obtain a copy of the License at
|
|
7
|
+
#
|
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
#
|
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
# See the License for the specific language governing permissions and
|
|
14
|
+
# limitations under the License.
|
|
15
|
+
#++
|
|
16
|
+
|
|
17
|
+
module StoreAgent
|
|
18
|
+
# バリデーションに使用するメソッドを定義したモジュール
|
|
19
|
+
module Validator
|
|
20
|
+
# 文字列またはシンボルでないとエラー
|
|
21
|
+
def validates_to_be_string_or_symbol!(value)
|
|
22
|
+
case
|
|
23
|
+
when value.nil?, value == "", value == :""
|
|
24
|
+
raise ArgumentError, "#{value} is empty string or symbol"
|
|
25
|
+
when !value.is_a?(String) && !value.is_a?(Symbol)
|
|
26
|
+
raise ArgumentError, "#{value} is not string or symbol"
|
|
27
|
+
else
|
|
28
|
+
true
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# 文字列中に '/' を含むとエラー
|
|
33
|
+
def validates_to_be_excluded_slash!(value)
|
|
34
|
+
if value.to_s.include?("/")
|
|
35
|
+
raise ArgumentError, "#{value} includes '/'"
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# スーパーユーザーのIDと一致している場合エラー
|
|
40
|
+
def validates_to_be_not_superuser_identifier!(value)
|
|
41
|
+
if value.to_s == StoreAgent.config.superuser_identifier
|
|
42
|
+
raise ArgumentError, "#{value} is reserved for superuser"
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# ゲストユーザーのIDと一致している場合エラー
|
|
47
|
+
def validates_to_be_not_guest_identifier!(value)
|
|
48
|
+
if value.to_s == StoreAgent.config.guest_identifier
|
|
49
|
+
raise ArgumentError, "#{value} is reserved for guest"
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# アクセサが nil を返す場合エラー
|
|
54
|
+
def validates_to_be_not_nil_value!(accessor_method_name)
|
|
55
|
+
if send(accessor_method_name).nil?
|
|
56
|
+
raise ArgumentError, "#{accessor_method_name} is nil"
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
#--
|
|
2
|
+
# Copyright 2015 realglobe, Inc.
|
|
3
|
+
#
|
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
# you may not use this file except in compliance with the License.
|
|
6
|
+
# You may obtain a copy of the License at
|
|
7
|
+
#
|
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
#
|
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
# See the License for the specific language governing permissions and
|
|
14
|
+
# limitations under the License.
|
|
15
|
+
#++
|
|
16
|
+
|
|
17
|
+
module StoreAgent
|
|
18
|
+
VERSION = "1.0.0"
|
|
19
|
+
end
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
#--
|
|
2
|
+
# Copyright 2015 realglobe, Inc.
|
|
3
|
+
#
|
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
# you may not use this file except in compliance with the License.
|
|
6
|
+
# You may obtain a copy of the License at
|
|
7
|
+
#
|
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
#
|
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
# See the License for the specific language governing permissions and
|
|
14
|
+
# limitations under the License.
|
|
15
|
+
#++
|
|
16
|
+
|
|
17
|
+
require "store_agent/version_manager/rugged_git"
|
|
18
|
+
require "store_agent/version_manager/ruby_git"
|
|
19
|
+
|
|
20
|
+
module StoreAgent
|
|
21
|
+
# バージョン管理に使用するクラスの雛形。<br>
|
|
22
|
+
# デフォルトではこのクラスが使用されるが、その場合はバージョン管理を行わない。
|
|
23
|
+
class VersionManager
|
|
24
|
+
attr_reader :workspace
|
|
25
|
+
|
|
26
|
+
# バージョン管理システムが使用するため予約されているファイル名<br>
|
|
27
|
+
# 例えば git の場合は、.git .keep など
|
|
28
|
+
def self.reserved_filenames
|
|
29
|
+
[]
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def initialize(workspace: nil) # :nodoc:
|
|
33
|
+
@workspace = workspace
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# :call-seq:
|
|
37
|
+
# init
|
|
38
|
+
#
|
|
39
|
+
# バージョン管理対象のリポジトリを初期化する
|
|
40
|
+
def init(*params, &block)
|
|
41
|
+
call_block(params, &block)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# :call-seq:
|
|
45
|
+
# add(*paths)
|
|
46
|
+
#
|
|
47
|
+
# 引数で渡されたパスをバージョン管理対象に追加する
|
|
48
|
+
def add(*params, &block)
|
|
49
|
+
call_block(params, &block)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# :call-seq:
|
|
53
|
+
# remove(*paths, directory: false)
|
|
54
|
+
#
|
|
55
|
+
# 引数で渡されたパスをバージョン管理対象から除外する<br>
|
|
56
|
+
# パスがディレクトリの場合には、directory に true が渡される
|
|
57
|
+
def remove(*params, &block)
|
|
58
|
+
call_block(params, &block)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# :call-seq:
|
|
62
|
+
# transaction(messsage, &block)
|
|
63
|
+
#
|
|
64
|
+
# 引数でコミットメッセージとブロックを受け取り、トランザクション処理で実行する<br>
|
|
65
|
+
# ブロックの実行に成功した場合には受け取ったメッセージで変更をコミットする。<br>
|
|
66
|
+
# 処理に失敗した場合は、ブロックの実行前の状態に戻す。
|
|
67
|
+
def transaction(*params, &block)
|
|
68
|
+
call_block(params, &block)
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
# :call-seq:
|
|
72
|
+
# read(path: "", revision: nil)
|
|
73
|
+
#
|
|
74
|
+
# 指定されたパスの指定リビジョン時の中身を返す
|
|
75
|
+
def read(*params, &block)
|
|
76
|
+
call_block(params, &block)
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
# :call-seq:
|
|
80
|
+
# revisions(path)
|
|
81
|
+
#
|
|
82
|
+
# 引数で渡されたパスのリビジョン一覧を返す
|
|
83
|
+
def revisions(*params, &block)
|
|
84
|
+
call_block(params, &block)
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
private
|
|
88
|
+
|
|
89
|
+
def relative_path(path)
|
|
90
|
+
path[(workspace.namespace_dirname.length + 1)..-1]
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def call_block(*, &block)
|
|
94
|
+
FileUtils.cd(workspace.namespace_dirname) do
|
|
95
|
+
if block
|
|
96
|
+
yield
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
end
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
#--
|
|
2
|
+
# Copyright 2015 realglobe, Inc.
|
|
3
|
+
#
|
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
# you may not use this file except in compliance with the License.
|
|
6
|
+
# You may obtain a copy of the License at
|
|
7
|
+
#
|
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
#
|
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
# See the License for the specific language governing permissions and
|
|
14
|
+
# limitations under the License.
|
|
15
|
+
#++
|
|
16
|
+
|
|
17
|
+
module StoreAgent
|
|
18
|
+
class VersionManager
|
|
19
|
+
# ruby-git(https://github.com/schacon/ruby-git) を使用してバージョン管理を行うクラス<br>
|
|
20
|
+
# StoreAgent::VersionManager を継承しているので、詳細はそちらを参照
|
|
21
|
+
class RubyGit < VersionManager
|
|
22
|
+
# :enddoc:
|
|
23
|
+
def self.reserved_filenames
|
|
24
|
+
%w(.git .keep)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def init
|
|
28
|
+
super do
|
|
29
|
+
Git.init
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def add(*paths)
|
|
34
|
+
super do
|
|
35
|
+
FileUtils.touch(paths)
|
|
36
|
+
repository.add(paths, force: true)
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def remove(*paths, **_)
|
|
41
|
+
super do
|
|
42
|
+
repository.remove(paths, recursive: true)
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def transaction(message)
|
|
47
|
+
if @transaction
|
|
48
|
+
yield
|
|
49
|
+
else
|
|
50
|
+
begin
|
|
51
|
+
@transaction = true
|
|
52
|
+
super do
|
|
53
|
+
yield
|
|
54
|
+
end
|
|
55
|
+
repository.commit(message)
|
|
56
|
+
rescue => e
|
|
57
|
+
repository.reset_hard
|
|
58
|
+
raise e
|
|
59
|
+
ensure
|
|
60
|
+
@transaction = false
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def read(path: "", revision: nil)
|
|
66
|
+
if path.end_with?("/")
|
|
67
|
+
read_directory(path: path, revision: revision)
|
|
68
|
+
else
|
|
69
|
+
read_file(path: path, revision: revision)
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def revisions(path = ".")
|
|
74
|
+
logs(path).map(&:objectish)
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
private
|
|
78
|
+
|
|
79
|
+
def repository
|
|
80
|
+
@repository ||= Git.open(workspace.namespace_dirname)
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def logs(path)
|
|
84
|
+
repository.log.path(path)
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def read_directory(path: ".", revision: "HEAD")
|
|
88
|
+
repository.gtree("#{revision}:#{relative_path(path)}").children.keys
|
|
89
|
+
rescue Git::GitExecuteError
|
|
90
|
+
raise StoreAgent::InvalidRevisionError.new(path: path, revision: revision)
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def read_file(path: ".", revision: "HEAD")
|
|
94
|
+
repository.gblob("#{revision}:#{relative_path(path)}").contents
|
|
95
|
+
rescue Git::GitExecuteError
|
|
96
|
+
raise StoreAgent::InvalidRevisionError.new(path: path, revision: revision)
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
end
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
#--
|
|
2
|
+
# Copyright 2015 realglobe, Inc.
|
|
3
|
+
#
|
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
# you may not use this file except in compliance with the License.
|
|
6
|
+
# You may obtain a copy of the License at
|
|
7
|
+
#
|
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
#
|
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
# See the License for the specific language governing permissions and
|
|
14
|
+
# limitations under the License.
|
|
15
|
+
#++
|
|
16
|
+
|
|
17
|
+
module StoreAgent
|
|
18
|
+
class VersionManager
|
|
19
|
+
# rugged(https://github.com/libgit2/rugged) を使用してバージョン管理を行うクラス<br>
|
|
20
|
+
# StoreAgent::VersionManager を継承しているので、詳細はそちらを参照
|
|
21
|
+
class RuggedGit < VersionManager
|
|
22
|
+
# :enddoc:
|
|
23
|
+
def self.reserved_filenames
|
|
24
|
+
%w(.git .keep)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def init
|
|
28
|
+
super do
|
|
29
|
+
Rugged::Repository.init_at(".")
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def add(*paths)
|
|
34
|
+
super do
|
|
35
|
+
FileUtils.touch(paths)
|
|
36
|
+
paths.flatten.each do |path|
|
|
37
|
+
oid = Rugged::Blob.from_workdir(repository, relative_path(path))
|
|
38
|
+
repository.index.add(relative_path(path))
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def remove(*paths, directory: false)
|
|
44
|
+
super do
|
|
45
|
+
paths.flatten.each do |path|
|
|
46
|
+
if directory
|
|
47
|
+
repository.index.remove_dir(relative_path(path))
|
|
48
|
+
else
|
|
49
|
+
repository.index.remove(relative_path(path))
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def transaction(message)
|
|
56
|
+
if @transaction
|
|
57
|
+
yield
|
|
58
|
+
else
|
|
59
|
+
begin
|
|
60
|
+
@transaction = true
|
|
61
|
+
super do
|
|
62
|
+
yield
|
|
63
|
+
end
|
|
64
|
+
commit(message)
|
|
65
|
+
rescue => e
|
|
66
|
+
repository.reset("HEAD", :hard)
|
|
67
|
+
raise e
|
|
68
|
+
ensure
|
|
69
|
+
@transaction = false
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def read(path: "", revision: nil)
|
|
75
|
+
if path.end_with?("/")
|
|
76
|
+
read_directory(path: path, revision: revision)
|
|
77
|
+
else
|
|
78
|
+
read_file(path: path, revision: revision)
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def revisions(path = "*")
|
|
83
|
+
logs(path).map(&:oid)
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
private
|
|
87
|
+
|
|
88
|
+
def repository
|
|
89
|
+
@repository ||= Rugged::Repository.new(workspace.namespace_dirname)
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def walker
|
|
93
|
+
@walker ||= Rugged::Walker.new(repository)
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def logs(path)
|
|
97
|
+
walker.sorting(Rugged::SORT_DATE)
|
|
98
|
+
walker.push(repository.head.target)
|
|
99
|
+
walker.select do |commit|
|
|
100
|
+
commit.parents.size == 1 && commit.diff(paths: [path]).size > 0
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def lookup_path(path: "", revision: nil)
|
|
105
|
+
paths = relative_path(path).split("/")
|
|
106
|
+
paths.inject(repository.lookup(revision).tree) do |tree, path|
|
|
107
|
+
repository.lookup(tree.find{|t| t[:name] == path}[:oid])
|
|
108
|
+
end
|
|
109
|
+
rescue Rugged::InvalidError
|
|
110
|
+
raise StoreAgent::InvalidRevisionError.new(path: path, revision: revision)
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def read_directory(path: "", revision: nil)
|
|
114
|
+
lookup_path(path: path, revision: revision).map{|t| t[:name]}
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
def read_file(path: "", revision: nil)
|
|
118
|
+
lookup_path(path: path, revision: revision).content
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
def commit(message)
|
|
122
|
+
options = {
|
|
123
|
+
tree: repository.index.write_tree(repository),
|
|
124
|
+
message: message,
|
|
125
|
+
parents: repository.empty? ? [] : [ repository.head.target ].compact,
|
|
126
|
+
update_ref: "HEAD"
|
|
127
|
+
}
|
|
128
|
+
Rugged::Commit.create(repository, options)
|
|
129
|
+
repository.index.write
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
end
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
#--
|
|
2
|
+
# Copyright 2015 realglobe, Inc.
|
|
3
|
+
#
|
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
# you may not use this file except in compliance with the License.
|
|
6
|
+
# You may obtain a copy of the License at
|
|
7
|
+
#
|
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
#
|
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
# See the License for the specific language governing permissions and
|
|
14
|
+
# limitations under the License.
|
|
15
|
+
#++
|
|
16
|
+
|
|
17
|
+
module StoreAgent
|
|
18
|
+
# ワークスペース
|
|
19
|
+
class Workspace
|
|
20
|
+
extend Forwardable
|
|
21
|
+
include StoreAgent::Validator
|
|
22
|
+
|
|
23
|
+
attr_reader :current_user, :namespace, :version_manager
|
|
24
|
+
def_delegators :root, *%w(find_object directory file exists?)
|
|
25
|
+
|
|
26
|
+
def initialize(current_user: nil, namespace: nil) # :nodoc:
|
|
27
|
+
@current_user = current_user
|
|
28
|
+
@namespace = namespace
|
|
29
|
+
validates_to_be_not_nil_value!(:current_user)
|
|
30
|
+
validates_to_be_string_or_symbol!(@namespace)
|
|
31
|
+
validates_to_be_excluded_slash!(@namespace)
|
|
32
|
+
@version_manager = StoreAgent.config.version_manager.new(workspace: self)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# ワークスペースを新規作成する
|
|
36
|
+
def create
|
|
37
|
+
if exists?
|
|
38
|
+
raise InvalidPathError, "workspace #{@namespace} is already exists"
|
|
39
|
+
end
|
|
40
|
+
FileUtils.mkdir_p(namespace_dirname)
|
|
41
|
+
@version_manager.init
|
|
42
|
+
root.create
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# ワークスペースを削除する
|
|
46
|
+
def delete
|
|
47
|
+
if !exists?
|
|
48
|
+
raise InvalidPathError, "workspace #{@namespace} not found"
|
|
49
|
+
end
|
|
50
|
+
FileUtils.remove_dir(namespace_dirname)
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# ワークスペースのファイルツリーの最上位ノード
|
|
54
|
+
def root
|
|
55
|
+
@root ||= StoreAgent::Node::DirectoryObject.new(workspace: self, path: "/")
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# ワークスペースの絶対パス
|
|
59
|
+
def namespace_dirname
|
|
60
|
+
File.absolute_path("#{StoreAgent.config.storage_root}/#{@namespace}")
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
# ストレージとして使用する領域の絶対パス
|
|
64
|
+
def storage_dirname
|
|
65
|
+
File.absolute_path("#{namespace_dirname}/#{StoreAgent.config.storage_dirname}")
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# メタデータの保存に使用する領域の絶対パス
|
|
69
|
+
def metadata_dirname
|
|
70
|
+
File.absolute_path("#{namespace_dirname}/#{StoreAgent.config.metadata_dirname}")
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
# 権限情報の保存に使用する領域の絶対パス
|
|
74
|
+
def permission_dirname
|
|
75
|
+
File.absolute_path("#{namespace_dirname}/#{StoreAgent.config.permission_dirname}")
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
# 全ワークスペース名の一覧を配列で返す
|
|
79
|
+
def self.name_list
|
|
80
|
+
if !File.exists?(StoreAgent.config.storage_root)
|
|
81
|
+
FileUtils.mkdir(StoreAgent.config.storage_root)
|
|
82
|
+
end
|
|
83
|
+
FileUtils.cd(StoreAgent.config.storage_root) do
|
|
84
|
+
return Dir.glob("*", File::FNM_DOTMATCH) - StoreAgent.reserved_filenames
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
end
|