php-composer 0.1.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.
Files changed (41) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +10 -0
  3. data/.rspec +2 -0
  4. data/.rubocop.yml +1006 -0
  5. data/Gemfile +15 -0
  6. data/LICENSE.txt +21 -0
  7. data/README.md +35 -0
  8. data/Rakefile +1 -0
  9. data/lib/composer.rb +52 -0
  10. data/lib/composer/error.rb +8 -0
  11. data/lib/composer/json/json_file.rb +270 -0
  12. data/lib/composer/json/json_formatter.rb +159 -0
  13. data/lib/composer/json/json_validaton_error.rb +29 -0
  14. data/lib/composer/manager.rb +79 -0
  15. data/lib/composer/package/alias_package.rb +273 -0
  16. data/lib/composer/package/base_package.rb +130 -0
  17. data/lib/composer/package/complete_package.rb +55 -0
  18. data/lib/composer/package/dumper/hash_dumper.rb +169 -0
  19. data/lib/composer/package/link.rb +51 -0
  20. data/lib/composer/package/link_constraint/base_constraint.rb +36 -0
  21. data/lib/composer/package/link_constraint/empty_constraint.rb +35 -0
  22. data/lib/composer/package/link_constraint/multi_constraint.rb +67 -0
  23. data/lib/composer/package/link_constraint/specific_constraint.rb +41 -0
  24. data/lib/composer/package/link_constraint/version_constraint.rb +221 -0
  25. data/lib/composer/package/loader/hash_loader.rb +316 -0
  26. data/lib/composer/package/loader/json_loader.rb +47 -0
  27. data/lib/composer/package/loader/project_attributes_loader.rb +71 -0
  28. data/lib/composer/package/loader/project_root_package_loader.rb +28 -0
  29. data/lib/composer/package/package.rb +118 -0
  30. data/lib/composer/package/root_alias_package.rb +37 -0
  31. data/lib/composer/package/root_package.rb +37 -0
  32. data/lib/composer/package/version/version_parser.rb +583 -0
  33. data/lib/composer/package/version/version_selector.rb +106 -0
  34. data/lib/composer/provider.rb +94 -0
  35. data/lib/composer/repository/array_repository.rb +195 -0
  36. data/lib/composer/repository/filesystem_repository.rb +86 -0
  37. data/lib/composer/repository/writeable_array_repository.rb +60 -0
  38. data/lib/composer/version.rb +3 -0
  39. data/php-composer.gemspec +31 -0
  40. data/resources/composer-schema.json +421 -0
  41. metadata +188 -0
@@ -0,0 +1,106 @@
1
+ #
2
+ # This file was ported to ruby from Composer php source code file.
3
+ # Original Source: Composer\Package\Version\VersionParser.php
4
+ #
5
+ # (c) Nils Adermann <naderman@naderman.de>
6
+ # Jordi Boggiano <j.boggiano@seld.be>
7
+ #
8
+ # For the full copyright and license information, please view the LICENSE
9
+ # file that was distributed with this source code.
10
+ #
11
+
12
+ module Composer
13
+ module Package
14
+ module Version
15
+ # Selects the best possible version for a package
16
+ #
17
+ # PHP Authors:
18
+ # Ryan Weaver <ryan@knpuniversity.com>
19
+ #
20
+ # Ruby Authors:
21
+ # Ioannis Kappas <ikappas@devworks.gr>
22
+ class VersionSelector
23
+
24
+ def initialize(pool)
25
+ @pool = pool
26
+ end
27
+
28
+
29
+ # Given a concrete version, this returns a ~ constraint (when possible)
30
+ # that should be used, for example, in composer.json.
31
+ #
32
+ # For example:
33
+ # * 1.2.1 -> ~1.2
34
+ # * 1.2 -> ~1.2
35
+ # * v3.2.1 -> ~3.2
36
+ # * 2.0-beta.1 -> ~2.0@beta
37
+ # * dev-master -> ~2.1@dev (dev version with alias)
38
+ # * dev-master -> dev-master (dev versions are untouched)
39
+ #
40
+ # @param Package package
41
+ # @return string
42
+ def find_recommended_require_version(package)
43
+ version = package.version
44
+ if !package.is_dev
45
+ return transform_version(version, package.pretty_version, package.stability)
46
+ end
47
+
48
+ loader = Composer::Package::Loader::HashLoader.new(parser)
49
+ dumper = Composer::Package::Dumper::HashDumper.new
50
+
51
+ if (extra = loader.get_branch_alias(dumper.dump(package)))
52
+ if match = /^(\d+\.\d+\.\d+)(\.9999999)-dev$/.match(extra)
53
+ extra = "#{match[1]}.0"
54
+ extra.gsub!('.9999999', '.0')
55
+ return transform_version(extra, extra, 'dev')
56
+ end
57
+ end
58
+
59
+ package.pretty_version
60
+ end
61
+
62
+ private
63
+
64
+ def transform_version(version, pretty_version, stability)
65
+ # attempt to transform 2.1.1 to 2.1
66
+ # this allows you to upgrade through minor versions
67
+ semantic_version_parts = version.split('.')
68
+ op = '~'
69
+
70
+ # check to see if we have a semver-looking version
71
+ if semantic_version_parts.length == 4 && /^0\D?/.match(semantic_version_parts[3])
72
+ # remove the last parts (i.e. the patch version number and any extra)
73
+ if semantic_version_parts[0] === '0'
74
+ if semantic_version_parts[1] === '0'
75
+ semantic_version_parts[3] = '*'
76
+ else
77
+ semantic_version_parts[2] = '*'
78
+ semantic_version_parts.delete_at(3)
79
+ end
80
+ op = ''
81
+ else
82
+ semantic_version_parts.delete_at(3)
83
+ semantic_version_parts.delete_at(2)
84
+ end
85
+ version = semantic_version_parts.join('.')
86
+ else
87
+ return pretty_version
88
+ end
89
+
90
+ # append stability flag if not default
91
+ if stability != 'stable'
92
+ version << "@#{stability}"
93
+ end
94
+
95
+ # 2.1 -> ~2.1
96
+ op + version
97
+ end
98
+
99
+ def parser
100
+ @parser ||= Composer::Package::Version::VersionParser.new
101
+ @parser
102
+ end
103
+ end
104
+ end
105
+ end
106
+ end
@@ -0,0 +1,94 @@
1
+ module Composer
2
+ class Provider
3
+
4
+ BLANK_PROVIDER = { "packages"=>{} }
5
+
6
+ def initialize(project)
7
+ @project = project
8
+ @package_dumper = Composer::Package::Dumper::HashDumper.new
9
+ end
10
+
11
+ def add_package(package)
12
+
13
+ raise ArgumentError, 'package must be specified' unless package
14
+ # raise TypeError, 'package must be a subclass of Composer::Package::Package' unless package.kind_of?(Composer::Package::Package)
15
+
16
+ name = package.name
17
+ pretty_version = package.pretty_version
18
+
19
+ packages[name] ||= {}
20
+ packages[name][pretty_version] = @package_dumper.dump(package)
21
+
22
+ if packages[name].length >= 2
23
+ packages[name].keys.sort.each { |k| packages[name][k] = packages[name].delete k }
24
+ end
25
+
26
+ end
27
+
28
+ def rm_package(package)
29
+
30
+ raise ArgumentError, 'package must be specified' unless package
31
+ # raise TypeError, 'package must be a subclass of Composer::Package::Package' unless package.kind_of?(Composer::Package::Package)
32
+
33
+ name = package.name
34
+ pretty_version = package.pretty_version
35
+
36
+ if has_package?(name, pretty_version)
37
+ packages[name].delete(pretty_version)
38
+ if packages[name].empty?
39
+ packages.delete(name)
40
+ elsif packages[name].length >= 2
41
+ packages[name].keys.sort.each { |k| packages[name][k] = packages[name].delete k }
42
+ end
43
+ end
44
+
45
+ end
46
+
47
+ def clear_packages
48
+ @packages = {}
49
+ end
50
+
51
+ def has_package?(name, pretty_version=nil)
52
+ if pretty_version
53
+ packages.key?(name) ? packages[name].key?(pretty_version) : false
54
+ else
55
+ packages.key?(name)
56
+ end
57
+ end
58
+
59
+ def has_packages?
60
+ !packages.empty?
61
+ end
62
+
63
+ def save_or_delete
64
+ if has_packages?
65
+ File.open(filepath, "w") { |f| f.write(content) }
66
+ else
67
+ File.delete(filepath) unless not File.exist?(filepath)
68
+ end
69
+ end
70
+
71
+ def filename
72
+ "project-#{@project.id}.json"
73
+ end
74
+
75
+ def sha1
76
+ Digest::SHA1.hexdigest content
77
+ end
78
+
79
+ private
80
+
81
+ def packages
82
+ @packages ||= File.exist?(filepath) ? File.open(filepath, "r") { |f| ActiveSupport::JSON.decode(f.read)["packages"] rescue {} } : {}
83
+ end
84
+
85
+ def content
86
+ { 'packages' => packages }.to_json
87
+ end
88
+
89
+ def filepath
90
+ File.join(File.realpath(Rails.root.join('public', 'p')), filename)
91
+ end
92
+
93
+ end
94
+ end
@@ -0,0 +1,195 @@
1
+ #
2
+ # This file was ported to ruby from Composer php source code.
3
+ # Original Source: Composer\Repository\ArrayRepository.php
4
+ #
5
+ # (c) Nils Adermann <naderman@naderman.de>
6
+ # Jordi Boggiano <j.boggiano@seld.be>
7
+ #
8
+ # For the full copyright and license information, please view the LICENSE
9
+ # file that was distributed with this source code.
10
+ #
11
+
12
+ module Composer
13
+ module Repository
14
+ class ArrayRepository
15
+ def initialize(packages = [])
16
+ packages.each do |package|
17
+ add_package(package)
18
+ end
19
+ end
20
+
21
+ def find_package(name, version = nil)
22
+ # normalize name
23
+ name = name.downcase
24
+
25
+ # normalize version
26
+ if version != nil
27
+ version_parser = Composer::Package::Verision::VersionParser.new
28
+ version = version_parser.normalize(version)
29
+ end
30
+
31
+ packages.each do |package|
32
+ if package.name === name && (nil === $version || version === package.version)
33
+ return package
34
+ end
35
+ end
36
+
37
+ end
38
+
39
+ def find_packages(name, version = nil)
40
+ # normalize name
41
+ name = name.downcase
42
+
43
+ # normalize version
44
+ if version != nil
45
+ version_parser = Composer::Package::Verision::VersionParser.new
46
+ version = version_parser.normalize(version)
47
+ end
48
+
49
+ matches = []
50
+ packages.each do |package|
51
+ if package.name === name && (nil === $version || version === package.version)
52
+ matches << package
53
+ end
54
+ end
55
+ matches
56
+ end
57
+
58
+ def search(query, full_search = false)
59
+ regex = /(?:#{query.split(/\s+/).join('|')})/i
60
+ matches = {}
61
+ packages.each do |package|
62
+ name = package.name
63
+
64
+ # allready matched
65
+ next if matches['name']
66
+
67
+ # search
68
+ if full_search
69
+ next unless (
70
+ package.instance_of(Composer::Package::CompletePackage) &&
71
+ regex.match("#{package.keywords.join(' ')} #{package.description}")
72
+ )
73
+ else
74
+ next unless (
75
+ full_search == false &&
76
+ regex.match(name)
77
+ )
78
+ end
79
+
80
+ matches[name] = {
81
+ 'name' => package.pretty_name,
82
+ 'description' => $package.description,
83
+ }
84
+ end
85
+ matches
86
+ end
87
+
88
+ def package?(package)
89
+ unless package
90
+ raise ArgumentError,
91
+ 'package must be specified'
92
+ end
93
+ unless package.is_a(Composer::Package::BasePackage)
94
+ raise TypeError,
95
+ 'package must be a class or superclass of \
96
+ Composer::Package::Package'
97
+ end
98
+
99
+ package_id = package.unique_name
100
+ packages.each do |repo_package|
101
+ return true if repo_package.unique_name === package_id
102
+ end
103
+
104
+ false
105
+ end
106
+
107
+ # Adds a new package to the repository
108
+ #
109
+ # Params:
110
+ # +package+ Package The package to add
111
+ def add_package(package)
112
+ unless package
113
+ raise ArgumentError,
114
+ 'package must be specified'
115
+ end
116
+ unless package.is_a(Composer::Package::BasePackage)
117
+ raise TypeError,
118
+ 'package must be a class or superclass of \
119
+ Composer::Package::Package'
120
+ end
121
+
122
+ initialize_repository unless @packages
123
+
124
+ package.repository = self
125
+
126
+ @packages << package
127
+
128
+ if package.instance_of(Composer::Package::AliasPackage)
129
+ aliased_package = package.alias_of
130
+ if aliased_package.repository === nil
131
+ add_package(aliased_package)
132
+ end
133
+ end
134
+ end
135
+
136
+ # Removes package from repository.
137
+ #
138
+ # Params:
139
+ # +package+ package instance to remove
140
+ def remove_package(package)
141
+ unless package
142
+ raise ArgumentError,
143
+ 'package must be specified'
144
+ end
145
+ unless package.is_a(Composer::Package::BasePackage)
146
+ raise TypeError,
147
+ 'package must be a class or superclass of \
148
+ Composer::Package::Package'
149
+ end
150
+
151
+ package_id = package.unique_name
152
+
153
+ index = 0
154
+ packages.each do |repo_package|
155
+ if repo_package.unique_name === package_id
156
+ @packages.delete_at(index)
157
+ return
158
+ end
159
+ index = index + 1
160
+ end
161
+ end
162
+
163
+ def packages
164
+ initialize_repository unless @packages
165
+ @packages
166
+ end
167
+
168
+ def count
169
+ @packages.lenght
170
+ end
171
+
172
+ protected
173
+
174
+ # Initializes the packages array.
175
+ # Mostly meant as an extension point.
176
+ def initialize_repository
177
+ @packages = []
178
+ end
179
+
180
+ def create_alias_package(package, version, pretty_version)
181
+ if package.instance_of(Composer::Package::AliasPackage)
182
+ alias_of = package.alias_of
183
+ else
184
+ alias_of = package
185
+ end
186
+ Composer::Package::AliasPackage.new(
187
+ alias_of,
188
+ version,
189
+ pretty_version
190
+ )
191
+ end
192
+
193
+ end
194
+ end
195
+ end
@@ -0,0 +1,86 @@
1
+ #
2
+ # This file was ported to ruby from Composer php source code.
3
+ # Original Source: Composer\Repository\FilesystemRepository.php
4
+ #
5
+ # (c) Nils Adermann <naderman@naderman.de>
6
+ # Jordi Boggiano <j.boggiano@seld.be>
7
+ #
8
+ # For the full copyright and license information, please view the LICENSE
9
+ # file that was distributed with this source code.
10
+ #
11
+
12
+ module Composer
13
+ module Repository
14
+ # Filesystem repository.
15
+ #
16
+ # PHP Authors:
17
+ # Konstantin Kudryashov <ever.zet@gmail.com>
18
+ # Jordi Boggiano <j.boggiano@seld.be>
19
+ #
20
+ # Ruby Authors:
21
+ # Ioannis Kappas <ikappas@devworks.gr>
22
+ class FilesystemRepository < Composer::Repository::WritableArrayRepository
23
+
24
+ # Initializes filesystem repository.
25
+ # @param [Composer::Json::JsonFile] repository_file repository json file
26
+ def initialize(repository_file)
27
+ unless repository_file
28
+ raise ArgumentError,
29
+ 'repository_file must be specified'
30
+ end
31
+ unless repository_file.is_a(Composer::Json::JsonFile)
32
+ raise TypeError,
33
+ 'repository_file type must be a \
34
+ Composer::Json::JsonFile or superclass'
35
+ end
36
+ super([])
37
+ @file = repository_file
38
+ end
39
+
40
+
41
+ def reload
42
+ @packages = nil
43
+ configure
44
+ end
45
+
46
+ # Writes writable repository.
47
+ def write
48
+ data = []
49
+ dumper = Composer::Package::Dumper::HashDumper.new
50
+
51
+ canonical_packages.each { |package| data << dumper.dump(package) }
52
+
53
+ @file.write(data)
54
+ end
55
+
56
+ protected
57
+
58
+ # Initializes repository (reads file, or remote address).
59
+ def initialize_repository
60
+ super
61
+ return unless @file.exists
62
+
63
+ begin
64
+ packages_data = @file.read
65
+ unless packages_data.is_a(Hash)
66
+ raise UnexpectedValueError,
67
+ 'Could not parse package list from the repository'
68
+ end
69
+ rescue Exception => e
70
+ raise InvalidRepositoryError,
71
+ "Invalid repository data in #{@file.path}, \
72
+ packages could not be loaded: \
73
+ [#{e.class}] #{e.message}"
74
+ end
75
+
76
+ loader = Composer::Package::Loader::ArrayLoader.new(nil, true)
77
+ packages_data.each do |package_data|
78
+ package = loader.load(package_data)
79
+ add_package(package)
80
+ end
81
+
82
+ end
83
+
84
+ end
85
+ end
86
+ end