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.
- checksums.yaml +7 -0
- data/.gitignore +10 -0
- data/.rspec +2 -0
- data/.rubocop.yml +1006 -0
- data/Gemfile +15 -0
- data/LICENSE.txt +21 -0
- data/README.md +35 -0
- data/Rakefile +1 -0
- data/lib/composer.rb +52 -0
- data/lib/composer/error.rb +8 -0
- data/lib/composer/json/json_file.rb +270 -0
- data/lib/composer/json/json_formatter.rb +159 -0
- data/lib/composer/json/json_validaton_error.rb +29 -0
- data/lib/composer/manager.rb +79 -0
- data/lib/composer/package/alias_package.rb +273 -0
- data/lib/composer/package/base_package.rb +130 -0
- data/lib/composer/package/complete_package.rb +55 -0
- data/lib/composer/package/dumper/hash_dumper.rb +169 -0
- data/lib/composer/package/link.rb +51 -0
- data/lib/composer/package/link_constraint/base_constraint.rb +36 -0
- data/lib/composer/package/link_constraint/empty_constraint.rb +35 -0
- data/lib/composer/package/link_constraint/multi_constraint.rb +67 -0
- data/lib/composer/package/link_constraint/specific_constraint.rb +41 -0
- data/lib/composer/package/link_constraint/version_constraint.rb +221 -0
- data/lib/composer/package/loader/hash_loader.rb +316 -0
- data/lib/composer/package/loader/json_loader.rb +47 -0
- data/lib/composer/package/loader/project_attributes_loader.rb +71 -0
- data/lib/composer/package/loader/project_root_package_loader.rb +28 -0
- data/lib/composer/package/package.rb +118 -0
- data/lib/composer/package/root_alias_package.rb +37 -0
- data/lib/composer/package/root_package.rb +37 -0
- data/lib/composer/package/version/version_parser.rb +583 -0
- data/lib/composer/package/version/version_selector.rb +106 -0
- data/lib/composer/provider.rb +94 -0
- data/lib/composer/repository/array_repository.rb +195 -0
- data/lib/composer/repository/filesystem_repository.rb +86 -0
- data/lib/composer/repository/writeable_array_repository.rb +60 -0
- data/lib/composer/version.rb +3 -0
- data/php-composer.gemspec +31 -0
- data/resources/composer-schema.json +421 -0
- 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
|