social_snippet 0.0.9 → 0.0.10

Sign up to get free protection for your applications and to get access to all the features.
Files changed (70) hide show
  1. checksums.yaml +8 -8
  2. data/.travis.yml +11 -4
  3. data/README.md +6 -6
  4. data/Rakefile +19 -1
  5. data/lib/social_snippet.rb +11 -0
  6. data/lib/social_snippet/api/install_repository_api.rb +23 -82
  7. data/lib/social_snippet/api/manifest_api.rb +3 -3
  8. data/lib/social_snippet/api/update_repository_api.rb +34 -35
  9. data/lib/social_snippet/command_line/sspm/sub_commands/install_command.rb +7 -7
  10. data/lib/social_snippet/config.rb +18 -8
  11. data/lib/social_snippet/core.rb +13 -0
  12. data/lib/social_snippet/document.rb +2 -0
  13. data/lib/social_snippet/document_backend.rb +2 -0
  14. data/lib/social_snippet/document_backend/yaml_document.rb +252 -0
  15. data/lib/social_snippet/document_backend/yaml_document/query.rb +45 -0
  16. data/lib/social_snippet/repository.rb +2 -2
  17. data/lib/social_snippet/repository/driver_factory.rb +42 -0
  18. data/lib/social_snippet/repository/drivers.rb +3 -2
  19. data/lib/social_snippet/repository/drivers/driver_base.rb +100 -0
  20. data/lib/social_snippet/repository/drivers/entry.rb +11 -0
  21. data/lib/social_snippet/repository/drivers/git_driver.rb +100 -0
  22. data/lib/social_snippet/repository/models.rb +15 -0
  23. data/lib/social_snippet/repository/models/package.rb +97 -0
  24. data/lib/social_snippet/repository/models/repository.rb +94 -0
  25. data/lib/social_snippet/repository/repository_manager.rb +79 -67
  26. data/lib/social_snippet/resolvers/base_resolver.rb +13 -17
  27. data/lib/social_snippet/rspec/test_document.rb +305 -0
  28. data/lib/social_snippet/rspec/test_driver.rb +76 -0
  29. data/lib/social_snippet/rspec/test_storage.rb +459 -0
  30. data/lib/social_snippet/storage.rb +1 -0
  31. data/lib/social_snippet/storage_backend.rb +3 -0
  32. data/lib/social_snippet/storage_backend/file_system_storage.rb +71 -0
  33. data/lib/social_snippet/storage_backend/storage_base.rb +35 -0
  34. data/lib/social_snippet/version.rb +8 -3
  35. data/spec/helpers/codeclimate_helper.rb +1 -1
  36. data/spec/helpers/fakefs_helper.rb +10 -0
  37. data/spec/helpers/social_snippet_helper.rb +117 -0
  38. data/spec/lib/api/insert_snippet_spec.rb +95 -2
  39. data/spec/lib/api/update_repository_spec.rb +196 -0
  40. data/spec/lib/command_line/sspm_install_spec.rb +169 -180
  41. data/spec/lib/command_line/sspm_update_spec.rb +56 -0
  42. data/spec/lib/config_spec.rb +6 -8
  43. data/spec/lib/core_spec.rb +21 -38
  44. data/spec/lib/file_system_storage_spec.rb +170 -0
  45. data/spec/lib/insert_resolver_spec.rb +15 -2
  46. data/spec/lib/registry_client_spec.rb +6 -9
  47. data/spec/lib/repository/driver_base_spec.rb +89 -0
  48. data/spec/lib/repository/git_driver_spec.rb +10 -0
  49. data/spec/lib/repository/package_spec.rb +172 -0
  50. data/spec/lib/repository/repository_factory_spec.rb +67 -22
  51. data/spec/lib/repository/repository_manager_spec.rb +71 -114
  52. data/spec/lib/repository/repository_spec.rb +191 -0
  53. data/spec/lib/yaml_document_spec.rb +14 -0
  54. data/spec/spec_helper.rb +8 -93
  55. data/test/config_test.rb +6 -7
  56. data/test/driver_base_test.rb +201 -0
  57. data/test/git_driver_test.rb +51 -0
  58. data/test/insert_snippet_test.rb +256 -349
  59. data/test/repository_manager_test.rb +7 -16
  60. data/test/yaml_document_test.rb +97 -0
  61. metadata +44 -16
  62. data/lib/social_snippet/repository/drivers/base_repository.rb +0 -189
  63. data/lib/social_snippet/repository/drivers/git_repository.rb +0 -74
  64. data/lib/social_snippet/repository/repository_factory.rb +0 -59
  65. data/lib/social_snippet/repository/repository_installer.rb +0 -85
  66. data/spec/lib/repository/base_repository_spec.rb +0 -104
  67. data/spec/lib/repository/git_repository_spec.rb +0 -83
  68. data/spec/lib/repository/repository_installer_spec.rb +0 -63
  69. data/test/base_repository_test.rb +0 -375
  70. data/test/git_repository_test.rb +0 -114
@@ -0,0 +1,11 @@
1
+ class ::SocialSnippet::Repository::Drivers::Entry
2
+
3
+ attr_reader :path
4
+ attr_reader :data
5
+
6
+ def initialize(new_path, new_data = nil)
7
+ @path = new_path
8
+ @data = new_data
9
+ end
10
+
11
+ end
@@ -0,0 +1,100 @@
1
+ module SocialSnippet::Repository::Drivers
2
+
3
+ class GitDriver < DriverBase
4
+
5
+ attr_reader :rugged_repo
6
+
7
+ def fetch
8
+ dest_dir = ::Dir.mktmpdir
9
+ @rugged_repo = ::Rugged::Repository.clone_at(url, dest_dir)
10
+ end
11
+
12
+ def snippet_json
13
+ @snippet_json ||= read_snippet_json
14
+ end
15
+
16
+ def read_snippet_json
17
+ oid = rugged_repo.head.target.tree["snippet.json"][:oid]
18
+ @snippet_json ||= ::JSON.parse rugged_repo.lookup(oid).read_raw.data
19
+ end
20
+
21
+ def read_file(oid)
22
+ rugged_repo.lookup(oid).read_raw.data
23
+ end
24
+
25
+ def each_directory(ref)
26
+ rugged_ref(ref).target.tree.each do |c|
27
+ next unless c[:type] == :tree
28
+ yield ::SocialSnippet::Repository::Drivers::Entry.new(c[:name])
29
+ end
30
+ end
31
+
32
+ def each_file(ref, &block)
33
+ walk_tree rugged_ref(ref).target.tree, ::Array.new, &block
34
+ end
35
+
36
+ def walk_tree(tree, parents)
37
+ tree.each_blob do |c|
38
+ path = ::File.join(*parents, c[:name])
39
+ yield ::SocialSnippet::Repository::Drivers::Entry.new(path, read_file(c[:oid]))
40
+ end
41
+ tree.each_tree do |t|
42
+ parents.push t[:name]
43
+ walk_tree(rugged_repo.lookup(t[:oid]), parents) do |content|
44
+ yield content
45
+ end
46
+ parents.pop
47
+ end
48
+ end
49
+
50
+ def current_ref
51
+ rugged_repo.head.name.gsub /^refs\/heads\//, ""
52
+ end
53
+
54
+ def rugged_ref(ref_name)
55
+ rugged_repo.references.each("refs/*/#{ref_name}").first
56
+ end
57
+
58
+ def rev_hash(ref)
59
+ rugged_ref(ref).target_id
60
+ end
61
+
62
+ def refs
63
+ all_refs = []
64
+ all_refs.concat remote_refs
65
+ all_refs.concat tags
66
+ all_refs
67
+ end
68
+
69
+ def remote_refs
70
+ rugged_repo.references.each("refs/remotes/origin/**/*").map do |r|
71
+ r.name.match(/^refs\/remotes\/origin\/(.*)/)[1]
72
+ end
73
+ end
74
+
75
+ def tags
76
+ rugged_repo.references.each("refs/tags/**/*").map do |r|
77
+ r.name.match(/^refs\/tags\/(.*)/)[1]
78
+ end
79
+ end
80
+
81
+ class << self
82
+
83
+ def target_url?(url)
84
+ uri = ::URI.parse(url)
85
+ is_git_uri(uri)
86
+ end
87
+
88
+ def is_git_uri(uri)
89
+ /git|https?/ === uri.scheme
90
+ end
91
+
92
+ def target_path?(path)
93
+ ::File.directory?(path) && ::File.directory?(::File.join path, ".git")
94
+ end
95
+
96
+ end # class << self
97
+
98
+ end # GitDriver
99
+
100
+ end # SocialSnippet
@@ -0,0 +1,15 @@
1
+ module SocialSnippet::Repository::Models
2
+
3
+ def self.const_missing(name)
4
+ if name === :Package
5
+ require_relative "models/package"
6
+ ::SocialSnippet::Repository::Models::Package
7
+ elsif name === :Repository
8
+ require_relative "models/repository"
9
+ ::SocialSnippet::Repository::Models::Repository
10
+ else
11
+ super
12
+ end
13
+ end
14
+
15
+ end
@@ -0,0 +1,97 @@
1
+ module SocialSnippet::Repository::Models
2
+
3
+ class Package < ::SocialSnippet::Document
4
+
5
+ @@core = nil
6
+
7
+ field :repo_name, :type => String # key
8
+ field :rev_hash, :type => String # key
9
+ field :name, :type => String
10
+ field :paths, :type => Array, :default => ::Array.new
11
+ field :dependencies, :type => Hash, :default => ::Hash.new
12
+
13
+ def display_name
14
+ name || "#{repo_name}@#{rev_hash}"
15
+ end
16
+
17
+ def normalize_path(path)
18
+ ::Pathname.new(path).cleanpath.to_s
19
+ end
20
+
21
+ def add_path(path)
22
+ push :paths => path
23
+ end
24
+
25
+ def add_directory(path)
26
+ path = normalize_path(path)
27
+ add_path path + "/"
28
+ dir_path = real_path(path)
29
+ core.storage.mkdir_p dir_path
30
+ end
31
+
32
+ def add_file(path, data)
33
+ path = normalize_path(path)
34
+ add_path path
35
+ file_path = real_path(path)
36
+ core.storage.mkdir_p ::File.dirname(file_path)
37
+ core.storage.write file_path, data
38
+ end
39
+
40
+ def add_dependency(name, ref)
41
+ modifier = {}
42
+ modifier[name] = ref
43
+ push :dependencies => modifier
44
+ end
45
+
46
+ def has_dependencies?
47
+ not dependencies.empty?
48
+ end
49
+
50
+ def snippet_json_text
51
+ json_path = real_path("snippet.json")
52
+ core.storage.read json_path
53
+ end
54
+
55
+ def snippet_json
56
+ @snippet_json ||= parse_snippet_json
57
+ end
58
+
59
+ def parse_snippet_json
60
+ ::JSON.parse(snippet_json_text)
61
+ end
62
+
63
+ def glob(glob_pattern)
64
+ paths.select do |path|
65
+ ::File.fnmatch glob_pattern, path, ::File::FNM_PATHNAME
66
+ end
67
+ end
68
+
69
+ def real_path(path = nil)
70
+ core.config.package_path repo_name, rev_hash, path
71
+ end
72
+
73
+ # path from snippet_json["main"]
74
+ def snippet_path(path = nil)
75
+ if snippet_json["main"].nil?
76
+ real_path path
77
+ else
78
+ real_path ::File.join(snippet_json["main"], path)
79
+ end
80
+ end
81
+
82
+ def core
83
+ @@core
84
+ end
85
+
86
+ def self.core
87
+ @@core
88
+ end
89
+
90
+ def self.core=(new_core)
91
+ @@core = new_core
92
+ end
93
+
94
+ end # Package
95
+
96
+ end # ::SocialSnippet::Repository::Models
97
+
@@ -0,0 +1,94 @@
1
+ module SocialSnippet::Repository::Models
2
+
3
+ class Repository < ::SocialSnippet::Document
4
+
5
+ @@core = nil
6
+
7
+ field :url, :type => String
8
+ field :name, :type => String
9
+ field :current_ref, :type => String
10
+ field :refs, :type => Array, :default => ::Array.new
11
+ # rev_hash[ref] => Commit ID
12
+ field :rev_hash, :type => Hash, :default => ::Hash.new
13
+ # package_refs[ref] => rev_hash
14
+ field :package_refs, :type => Hash, :default => ::Hash.new
15
+
16
+ def add_package(ref)
17
+ modifier = ::Hash.new
18
+ modifier[ref] = rev_hash[ref]
19
+ push :package_refs => modifier
20
+ end
21
+
22
+ def add_ref(ref, rev_hash)
23
+ add_to_set :refs => ref
24
+ modifier = ::Hash.new
25
+ modifier[ref] = rev_hash
26
+ push :rev_hash => modifier
27
+ end
28
+
29
+ def has_ref?(ref)
30
+ refs.include? ref
31
+ end
32
+
33
+ def package_ref_keys
34
+ package_refs.map {|k, _| k }
35
+ end
36
+
37
+ def package_minor_versions
38
+ package_versions.map do |v|
39
+ ::SocialSnippet::Version.minor v
40
+ end.uniq
41
+ end
42
+
43
+ def latest_package_version(pattern = "")
44
+ find_latest_version package_versions, pattern
45
+ end
46
+
47
+ def package_versions
48
+ select_versions package_ref_keys
49
+ end
50
+
51
+ # Returns latest version
52
+ def latest_version(pattern = "")
53
+ find_latest_version versions, pattern
54
+ end
55
+
56
+ # Returns all versions
57
+ def versions
58
+ select_versions refs
59
+ end
60
+
61
+ def find_latest_version(versions, pattern = "")
62
+ matches = versions.select {|ref| ::SocialSnippet::Version.is_matched_version_pattern(pattern, ref)}
63
+ ::VersionSorter.rsort(matches).first
64
+ end
65
+
66
+ def select_versions(refs)
67
+ refs.select {|ref| ::SocialSnippet::Version.is_version(ref) }
68
+ end
69
+
70
+ def has_package_versions?
71
+ not package_versions.empty?
72
+ end
73
+
74
+ # Check repository has version ref
75
+ def has_versions?
76
+ not versions.empty?
77
+ end
78
+
79
+ def core
80
+ @@core
81
+ end
82
+
83
+ def self.core
84
+ @@core
85
+ end
86
+
87
+ def self.core=(new_core)
88
+ @@core = new_core
89
+ end
90
+
91
+ end
92
+
93
+ end
94
+
@@ -2,9 +2,6 @@ module SocialSnippet::Repository
2
2
 
3
3
  class RepositoryManager
4
4
 
5
- attr_reader :installer
6
- attr_reader :repo_paths
7
- attr_reader :repo_cache_path
8
5
  attr_reader :core
9
6
 
10
7
  # Constructor
@@ -12,31 +9,6 @@ module SocialSnippet::Repository
12
9
  # @param new_core [::SocialSnippet::Core]
13
10
  def initialize(new_core)
14
11
  @core = new_core
15
- @installer = ::SocialSnippet::Repository::RepositoryInstaller.new(core)
16
- @repo_cache_path = core.config.repository_cache_path
17
- @repo_paths = []
18
-
19
- init_repo_paths
20
- init_repo_cache_path
21
- end
22
-
23
- def init_repo_cache_path
24
- ::FileUtils.mkdir_p repo_cache_path
25
- end
26
-
27
- def init_repo_paths
28
- repo_paths.push installer.path
29
- repo_paths.each {|path| ::FileUtils.mkdir_p path }
30
- end
31
-
32
- def deps(repo_name, repo_ref = nil)
33
- repo = find_repository(repo_name)
34
- repo.checkout(repo_ref) unless repo_ref.nil?
35
- repo.dependencies
36
- end
37
-
38
- def has_deps?(repo_name, repo_ref = nil)
39
- not deps(repo_name, repo_ref).empty?
40
12
  end
41
13
 
42
14
  # Get snippet by context and tag
@@ -53,8 +25,8 @@ module SocialSnippet::Repository
53
25
  # @param tag [::SocialSnippet::Tag] The tag of snippet
54
26
  def resolve_snippet_path(context, tag)
55
27
  if tag.has_repo?
56
- repo = find_repository_by_tag(tag)
57
- repo.real_path tag.path
28
+ pkg = find_package_by_tag(tag)
29
+ pkg.snippet_path tag.path
58
30
  else
59
31
  new_context = context.clone
60
32
  new_context.dirname + "/" + tag.filename
@@ -64,36 +36,38 @@ module SocialSnippet::Repository
64
36
  # Find repository by tag
65
37
  #
66
38
  # @param tag [::SocialSnippet::Tag] The tag of repository
67
- def find_repository_by_tag(tag)
39
+ def find_package_by_tag(tag)
68
40
  if tag.has_ref?
69
- find_repository(tag.repo, tag.ref)
41
+ find_package(tag.repo, tag.ref)
70
42
  else
71
- find_repository(tag.repo)
43
+ find_package(tag.repo)
72
44
  end
73
45
  end
74
46
 
75
47
  # Find repository by repo name
76
48
  #
77
49
  # @param name [String] The name of repository
78
- def find_repository(name, ref = nil)
79
- return nil if name.nil? || name.empty?
80
-
81
- repo_paths.each do |repo_path|
82
- path = "#{repo_path}/#{name}"
83
- if ::Dir.exists?(path)
84
- repo = RepositoryFactory.create(path, ref)
85
- repo.load_cache repo_cache_path
86
- return repo
87
- end
88
- end
50
+ def find_package(name, ref = nil)
51
+ repo = find_repository(name)
52
+ ref ||= repo.latest_package_version || repo.current_ref
53
+ raise "invalid references" unless repo.has_ref?(ref)
54
+ Models::Package.find_by(
55
+ :repo_name => name,
56
+ :rev_hash => repo.rev_hash[ref],
57
+ )
58
+ end
89
59
 
90
- nil
60
+ def find_repository(name)
61
+ Models::Repository.find_by(:name => name)
62
+ end
63
+
64
+ def find_repository_by_url(url)
65
+ Models::Repository.find_by(:url => url)
91
66
  end
92
67
 
93
68
  def find_repositories_start_with(prefix)
94
- glob_path = ::File.join(installer.path, "#{prefix}*")
95
- ::Dir.glob(glob_path).map do |repopath|
96
- Pathname(repopath).basename.to_s
69
+ Models::Repository.where(:name => /^#{prefix}.*/).map do |repo|
70
+ repo.name
97
71
  end
98
72
  end
99
73
 
@@ -103,12 +77,12 @@ module SocialSnippet::Repository
103
77
  end
104
78
 
105
79
  def complete_file_name(keyword)
106
- repo_name = get_repo_name(keyword)
107
- repo = find_repository(repo_name)
108
- file_path = get_file_path_prefix(keyword)
109
- glob_path = "#{file_path}*"
80
+ repo_name = get_repo_name(keyword)
81
+ package = find_package(repo_name)
82
+ file_path = keyword_filepath(keyword)
83
+ glob_path = "#{file_path}*"
110
84
 
111
- repo.glob(glob_path).map do |cand_file_path|
85
+ package.glob(glob_path).map do |cand_file_path|
112
86
  if ::File.directory?(cand_file_path)
113
87
  Pathname(cand_file_path).basename.to_s + "/"
114
88
  else
@@ -135,7 +109,7 @@ module SocialSnippet::Repository
135
109
  /^[^@]*@[^<]+<([^:#>]*[^:#>])$/.match(keyword)[1]
136
110
  end
137
111
 
138
- def get_file_path_prefix(keyword)
112
+ def keyword_filepath(keyword)
139
113
  /^[^@]*@[^<]+<[^#:]+:([^>]*)$/.match(keyword)[1]
140
114
  end
141
115
 
@@ -147,30 +121,68 @@ module SocialSnippet::Repository
147
121
  /^[^@]*@[^<]+<[^#:]+:[^>]*$/ === keyword
148
122
  end
149
123
 
150
- def cache_installing_repo(repo, options = {})
151
- repo.create_cache repo_cache_path
124
+ def install(url, ref, options = ::Hash.new)
125
+ driver = core.driver_factory.clone(url)
126
+ ref ||= resolve_ref_by_driver(driver)
127
+ repo = update_repository(driver, url)
128
+ create_package driver, ref
152
129
  end
153
130
 
154
- def fetch(repo_name, options)
155
- installer.fetch repo_name, options
131
+ def resolve_ref_by_driver(driver)
132
+ driver.latest_version || driver.current_ref
156
133
  end
157
134
 
158
- def update(repo_name, repo_ref, repo, options)
159
- cache_installing_repo repo, options
160
- installer.add repo_name, repo_ref
135
+ def update_repository(driver, url)
136
+ repo = Models::Repository.find_or_create_by(:url => url)
137
+ repo.update_attributes! :name => driver.snippet_json["name"]
138
+ driver.each_ref {|ref| repo.add_ref ref, driver.rev_hash(ref) }
139
+ repo
161
140
  end
162
141
 
163
- def install(repo_name, repo_ref, repo, options)
164
- installer.copy_repository repo, options
165
- update repo_name, repo_ref, repo, options
142
+ def create_package(driver, ref)
143
+ repo_name = driver.snippet_json["name"]
144
+ package = Models::Package.create(
145
+ :repo_name => repo_name,
146
+ :rev_hash => driver.rev_hash(ref),
147
+ :name => "#{driver.snippet_json["name"]}##{ref}",
148
+ )
149
+
150
+ repo = find_repository(repo_name)
151
+ repo.add_package ref
152
+
153
+ driver.each_directory(ref) do |dir|
154
+ package.add_directory dir.path
155
+ end
156
+ driver.each_file(ref) do |content|
157
+ package.add_file content.path, content.data
158
+ end
159
+
160
+ unless package.snippet_json["dependencies"].nil?
161
+ package.snippet_json["dependencies"].each do |dep_name, dep_ref|
162
+ package.add_dependency dep_name, dep_ref
163
+ end
164
+ end
165
+
166
+ package
166
167
  end
167
168
 
168
169
  def exists?(repo_name, repo_ref = nil)
169
- installer.exists? repo_name, repo_ref
170
+ # not found repo
171
+ return false unless Models::Repository.where(:name => repo_name).exists?
172
+
173
+ repo = Models::Repository.find_by(:name => repo_name)
174
+ if repo_ref.nil?
175
+ true
176
+ else
177
+ Models::Package.where(
178
+ :repo_name => repo_name,
179
+ :rev_hash => repo.rev_hash[repo_ref],
180
+ ).exists?
181
+ end
170
182
  end
171
183
 
172
- def each_installed_repo(&block)
173
- installer.each &block
184
+ def each_repo(&block)
185
+ Models::Repository.all.each &block
174
186
  end
175
187
 
176
188
  end # RepositoryManager