php-composer 0.4.5 → 1.0.0.pre.alpha11

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 (44) hide show
  1. checksums.yaml +4 -4
  2. data/.rbenv-gemsets +1 -0
  3. data/.rubocop.yml +131 -188
  4. data/.ruby-version +1 -0
  5. data/Gemfile +0 -9
  6. data/Rakefile +11 -0
  7. data/lib/composer.rb +52 -49
  8. data/lib/composer/json/json_file.rb +110 -83
  9. data/lib/composer/json/json_formatter.rb +43 -77
  10. data/lib/composer/json/{json_validaton_error.rb → json_validation_error.rb} +6 -2
  11. data/lib/composer/package/alias_package.rb +77 -61
  12. data/lib/composer/package/complete_package.rb +88 -18
  13. data/lib/composer/package/dumper/hash_dumper.rb +50 -118
  14. data/lib/composer/package/dumper/hash_dumper/complete_package_attribute_dumpers.rb +47 -0
  15. data/lib/composer/package/dumper/hash_dumper/package_attribute_dumpers.rb +145 -0
  16. data/lib/composer/package/dumper/hash_dumper/root_package_attribute_dumpers.rb +24 -0
  17. data/lib/composer/package/link.rb +15 -5
  18. data/lib/composer/package/loader/hash_loader.rb +92 -228
  19. data/lib/composer/package/loader/hash_loader/complete_package_attribute_loaders.rb +83 -0
  20. data/lib/composer/package/loader/hash_loader/package_attribute_loaders.rb +181 -0
  21. data/lib/composer/package/loader/hash_loader/root_package_attribute_loaders.rb +32 -0
  22. data/lib/composer/package/loader/json_loader.rb +7 -9
  23. data/lib/composer/package/package.rb +611 -43
  24. data/lib/composer/package/root_alias_package.rb +186 -15
  25. data/lib/composer/package/root_package.rb +12 -4
  26. data/lib/composer/package/version/version_parser.rb +16 -532
  27. data/lib/composer/package/version/version_selector.rb +127 -68
  28. data/lib/composer/repository/base_repository.rb +46 -3
  29. data/lib/composer/repository/composite_repository.rb +4 -4
  30. data/lib/composer/repository/filesystem_repository.rb +15 -8
  31. data/lib/composer/repository/hash_repository.rb +62 -45
  32. data/lib/composer/repository/writeable_hash_repository.rb +5 -5
  33. data/lib/composer/util/composer_mirror.rb +76 -0
  34. data/php-composer.gemspec +14 -8
  35. data/resources/composer-schema.json +12 -0
  36. metadata +117 -16
  37. data/lib/composer/error.rb +0 -8
  38. data/lib/composer/package/base_package.rb +0 -130
  39. data/lib/composer/package/link_constraint/base_constraint.rb +0 -36
  40. data/lib/composer/package/link_constraint/empty_constraint.rb +0 -35
  41. data/lib/composer/package/link_constraint/multi_constraint.rb +0 -67
  42. data/lib/composer/package/link_constraint/specific_constraint.rb +0 -41
  43. data/lib/composer/package/link_constraint/version_constraint.rb +0 -221
  44. data/lib/composer/version.rb +0 -3
@@ -1,17 +1,21 @@
1
- #
1
+ ##
2
2
  # This file was ported to ruby from Composer php source code file.
3
- # Original Source: Composer\Package\Version\VersionParser.php
3
+ #
4
+ # Original Source: Composer\Package\Version\VersionSelector.php
5
+ # Ref SHA: 966a9827382b59064255579f524e3904527abdbe
4
6
  #
5
7
  # (c) Nils Adermann <naderman@naderman.de>
6
8
  # Jordi Boggiano <j.boggiano@seld.be>
7
9
  #
8
10
  # For the full copyright and license information, please view the LICENSE
9
11
  # file that was distributed with this source code.
10
- #
12
+ ##
11
13
 
12
14
  module Composer
13
15
  module Package
14
16
  module Version
17
+
18
+ ##
15
19
  # Selects the best possible version for a package
16
20
  #
17
21
  # PHP Authors:
@@ -19,87 +23,142 @@ module Composer
19
23
  #
20
24
  # Ruby Authors:
21
25
  # Ioannis Kappas <ikappas@devworks.gr>
26
+ ##
22
27
  class VersionSelector
23
28
 
24
- def initialize(pool)
25
- @pool = pool
26
- end
29
+ def initialize(pool)
30
+ @pool = pool
31
+ end
32
+
33
+ ##
34
+ # Given a package name and optional version, returns the latest PackageInterface
35
+ # that matches.
36
+ #
37
+ # @param _package_name string
38
+ # @param _target_pkg_version string
39
+ # @param _target_php_version string
40
+ # @param _preferred_stability string
41
+ #
42
+ # @return Package|bool
43
+ ##
44
+ def find_best_candidate(_package_name, _target_pkg_version = nil, _target_php_version = nil, _preferred_stability = 'stable')
27
45
 
46
+ raise NotImplementedError
28
47
 
29
- # Given a concrete version, this returns a ~ constraint (when possible)
30
- # that should be used, for example, in composer.json.
48
+ # constraint = target_pkg_version ? parser.parse_constraints(target_pkg_version) : nil
49
+ # candidates = @pool.what_provides(package_name.downcase, constraint, true)
31
50
  #
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)
51
+ # if target_php_version
52
+ # php_constraint = ::Composer::Semver::Constraint::Constraint.new('==', parser.normalize(target_php_version))
53
+ # candidates = candidates.select do |pkg|
54
+ # requires = pkg.requires
55
+ # return ! requires['php'].nil? || requires['php'].constraint.matches(php_constraint)
56
+ # end
57
+ # end
39
58
  #
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
59
+ # return false unless candidates
60
+ #
61
+ # # select highest version if we have many
62
+ # package = reset(candidates)
63
+ # min_priority = ::Composer::Package::Package::stabilities[preferred_stability]
64
+ # candidates.each do |candidate|
65
+ # candidate_priority = candidate.stability_priority
66
+ # current_priority = package.stability_priority
67
+ #
68
+ # # candidate is less stable than our preferred stability, and we have a package that is more stable than it, so we skip it
69
+ # if min_priority < candidate_priority && current_priority < candidate_priority
70
+ # continue
71
+ # end
72
+ # # candidate is more stable than our preferred stability, and current package is less stable than preferred stability, then we select the candidate always
73
+ # if min_priority >= candidate_priority && min_priority < current_priority
74
+ # package = candidate
75
+ # continue
76
+ # end
77
+ #
78
+ # # select highest version of the two
79
+ # if version_compare(package.version, candidate.version, '<')
80
+ # package = candidate
81
+ # end
82
+ # end
83
+ #
84
+ # package
85
+ end
47
86
 
48
- loader = Composer::Package::Loader::HashLoader.new(parser)
49
- dumper = Composer::Package::Dumper::HashDumper.new
87
+ ##
88
+ # Given a concrete version, this returns a ~ constraint (when possible)
89
+ # that should be used, for example, in composer.json.
90
+ #
91
+ # For example:
92
+ # * 1.2.1 -> ~1.2
93
+ # * 1.2 -> ~1.2
94
+ # * v3.2.1 -> ~3.2
95
+ # * 2.0-beta.1 -> ~2.0@beta
96
+ # * dev-master -> ~2.1@dev (dev version with alias)
97
+ # * dev-master -> dev-master (dev versions are untouched)
98
+ #
99
+ # @param package Package
100
+ # @return string
101
+ ##
102
+ def find_recommended_require_version(package)
103
+ version = package.version
104
+ unless package.is_dev?
105
+ return transform_version(version, package.pretty_version, package.stability)
106
+ end
50
107
 
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
108
+ loader = ::Composer::Package::Loader::HashLoader.new(parser)
109
+ dumper = ::Composer::Package::Dumper::HashDumper.new
58
110
 
59
- package.pretty_version
111
+ extra = loader.get_branch_alias(dumper.dump(package))
112
+ if extra =~ /^(\d+\.\d+\.\d+)(\.9999999)-dev$/
113
+ extra = "#{$1}.0"
114
+ extra.gsub!('.9999999', '.0')
115
+ return transform_version(extra, extra, 'dev')
60
116
  end
61
117
 
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
118
+ package.pretty_version
119
+ end
89
120
 
90
- # append stability flag if not default
91
- if stability != 'stable'
92
- version << "@#{stability}"
93
- end
121
+ private
122
+
123
+ def transform_version(version, pretty_version, stability)
124
+ # attempt to transform 2.1.1 to 2.1
125
+ # this allows you to upgrade through minor versions
126
+ semantic_version_parts = version.split('.')
127
+ op = '~'
94
128
 
95
- # 2.1 -> ~2.1
96
- op + version
129
+ # check to see if we have a semver-looking version
130
+ if semantic_version_parts.length == 4 && /^0\D?/.match(semantic_version_parts[3])
131
+ # remove the last parts (i.e. the patch version number and any extra)
132
+ if semantic_version_parts[0] === '0'
133
+ if semantic_version_parts[1] === '0'
134
+ semantic_version_parts[3] = '*'
135
+ else
136
+ semantic_version_parts[2] = '*'
137
+ semantic_version_parts.delete_at(3)
138
+ end
139
+ op = ''
140
+ else
141
+ semantic_version_parts.delete_at(3)
142
+ semantic_version_parts.delete_at(2)
143
+ end
144
+ version = semantic_version_parts.join('.')
145
+ else
146
+ return pretty_version
97
147
  end
98
148
 
99
- def parser
100
- @parser ||= Composer::Package::Version::VersionParser.new
101
- @parser
149
+ # append stability flag if not default
150
+ if stability != 'stable'
151
+ version << "@#{stability}"
102
152
  end
153
+
154
+ # 2.1 -> ~2.1
155
+ op + version
156
+ end
157
+
158
+ def parser
159
+ @parser ||= ::Composer::Semver::VersionParser.new
160
+ end
161
+
103
162
  end
104
163
  end
105
164
  end
@@ -24,22 +24,65 @@ module Composer
24
24
  SEARCH_FULLTEXT = 0
25
25
  SEARCH_NAME = 1
26
26
 
27
- def package?
27
+ ##
28
+ # Determine whether the specified package is registered (installed).
29
+ #
30
+ # @param package ::Composer::Package::Package
31
+ # The package to check for.
32
+ # @return bool
33
+ # True if the package is registered; Otherwise false.
34
+ #
35
+ def package?(package)
28
36
  # implement inside child
29
37
  end
30
38
 
31
- def find_package(name, version)
39
+ ##
40
+ # Searches for the first match of a package by name and version.
41
+ #
42
+ # @param name string
43
+ # The package name.
44
+ # @param constraint string|::Composer::Semver::Constraint::Constraint
45
+ # The package version or version constraint to match against
46
+ #
47
+ # @return PackageInterface|nil
48
+ #
49
+ def find_package(name, constraint)
32
50
  # implement inside child
33
51
  end
34
52
 
35
- def find_packages(name, version = nil)
53
+ ##
54
+ # Searches for all packages matching a name and optionally a version.
55
+ #
56
+ # @param name string
57
+ # The package name.
58
+ # @param constraint string|::Composer::Semver::Constraint::Constraint
59
+ # Optional. The package version or version constraint to match against.
60
+ #
61
+ # @return ::Composer::Package::Package[]
62
+ ##
63
+ def find_packages(name, constraint = nil)
36
64
  # implement inside child
37
65
  end
38
66
 
67
+ ##
68
+ # Returns list of registered packages.
69
+ #
70
+ # @return ::Composer::Package::Package[]
71
+ ##
39
72
  def packages
40
73
  # implement inside child
41
74
  end
42
75
 
76
+ ##
77
+ # Searches the repository for packages containing the query
78
+ #
79
+ # @param query string
80
+ # The search query
81
+ # @param mode integer
82
+ # A set of SEARCH_* constants to search on, implementations should do a best effort only.
83
+ #
84
+ # @return hash[] an array of hash { 'name' => '...', 'description' => '...')
85
+ #
43
86
  def search(query, mode = 0)
44
87
  # implement inside child
45
88
  end
@@ -18,7 +18,7 @@ module Composer
18
18
  #
19
19
  # Ruby Authors:
20
20
  # Ioannis Kappas <ikappas@devworks.gr>
21
- class CompositeRepository < Composer::Repository::BaseRepository
21
+ class CompositeRepository < ::Composer::Repository::BaseRepository
22
22
  # Initializes filesystem repository.
23
23
  # @param [Array] repositories An array of repositories.
24
24
  def initialize(repositories)
@@ -114,17 +114,17 @@ module Composer
114
114
  raise ArgumentError,
115
115
  'repository must be specified'
116
116
  end
117
- unless repository.is_a?(Composer::Repository::BaseRepository)
117
+ unless repository.is_a?(::Composer::Repository::BaseRepository)
118
118
  raise TypeError,
119
119
  'repository type must be a \
120
120
  Composer::Repository::BaseRepository or superclass'
121
121
  end
122
- if repository.instance_of?(Composer::Repository::CompositeRepository)
122
+ if repository.instance_of?(::Composer::Repository::CompositeRepository)
123
123
  repository.repositories.each do |repo|
124
124
  add_repository(repo)
125
125
  end
126
126
  else
127
- @repositories.push(repository)
127
+ @repositories.push(repository)
128
128
  end
129
129
  end
130
130
  end
@@ -11,6 +11,8 @@
11
11
 
12
12
  module Composer
13
13
  module Repository
14
+
15
+ ##
14
16
  # Filesystem repository.
15
17
  #
16
18
  # PHP Authors:
@@ -19,19 +21,24 @@ module Composer
19
21
  #
20
22
  # Ruby Authors:
21
23
  # Ioannis Kappas <ikappas@devworks.gr>
22
- class FilesystemRepository < Composer::Repository::WritableHashRepository
24
+ ##
25
+ class FilesystemRepository < ::Composer::Repository::WritableHashRepository
23
26
 
27
+ ##
24
28
  # Initializes filesystem repository.
25
- # @param [Composer::Json::JsonFile] repository_file repository json file
29
+ #
30
+ # @param repository_file Composer::Json::JsonFile
31
+ # The repository json file
32
+ ##
26
33
  def initialize(repository_file)
27
34
  unless repository_file
28
35
  raise ArgumentError,
29
36
  'repository_file must be specified'
30
37
  end
31
- unless repository_file.is_a?(Composer::Json::JsonFile)
38
+ unless repository_file.is_a?(::Composer::Json::JsonFile)
32
39
  raise TypeError,
33
- 'repository_file type must be a \
34
- Composer::Json::JsonFile or superclass'
40
+ 'repository_file type must be a' \
41
+ 'Composer::Json::JsonFile or superclass'
35
42
  end
36
43
  super([])
37
44
  @file = repository_file
@@ -45,7 +52,7 @@ module Composer
45
52
  # Writes writable repository.
46
53
  def write
47
54
  data = []
48
- dumper = Composer::Package::Dumper::HashDumper.new
55
+ dumper = ::Composer::Package::Dumper::HashDumper.new
49
56
 
50
57
  canonical_packages.each { |package| data << dumper.dump(package) }
51
58
 
@@ -72,7 +79,7 @@ module Composer
72
79
  [#{e.class}] #{e.message}"
73
80
  end
74
81
 
75
- loader = Composer::Package::Loader::HashLoader.new(nil, true)
82
+ loader = ::Composer::Package::Loader::HashLoader.new(nil, true)
76
83
  packages_data.each do |package_data|
77
84
  package = loader.load(package_data)
78
85
  add_package(package)
@@ -82,4 +89,4 @@ module Composer
82
89
 
83
90
  end
84
91
  end
85
- end
92
+ end
@@ -9,22 +9,23 @@
9
9
  # file that was distributed with this source code.
10
10
  #
11
11
 
12
+ require 'composer/semver'
13
+
12
14
  module Composer
13
15
  module Repository
14
- class HashRepository < Composer::Repository::BaseRepository
16
+ class HashRepository < ::Composer::Repository::BaseRepository
17
+
15
18
  def initialize(packages = [])
16
- packages.each do |package|
17
- add_package(package)
18
- end
19
+ packages.each {|p| add_package p } if packages.instance_of? Array
19
20
  end
20
21
 
21
22
  def find_package(name, version = nil)
22
23
  # normalize name
23
- name = name.downcase
24
+ name.downcase! unless name.nil?
24
25
 
25
26
  # normalize version
26
- if !version.nil?
27
- version_parser = Composer::Package::Version::VersionParser.new
27
+ unless version.nil?
28
+ version_parser = ::Composer::Semver::VersionParser.new
28
29
  version = version_parser.normalize(version)
29
30
  end
30
31
 
@@ -41,47 +42,57 @@ module Composer
41
42
  end
42
43
 
43
44
  def find_packages(name, version = nil)
44
- # normalize name
45
- name = name.downcase
45
+ # normalize name
46
+ name.downcase! unless name.nil?
46
47
 
47
- # normalize version
48
- if version != nil
49
- version_parser = Composer::Package::Version::VersionParser.new
50
- version = version_parser.normalize(version)
51
- end
48
+ # normalize version
49
+ unless version.nil?
50
+ version_parser = ::Composer::Semver::VersionParser.new
51
+ version = version_parser.normalize(version)
52
+ end
52
53
 
53
- matches = []
54
- packages.each do |package|
55
- if package.name === name && (nil === version || version === package.version)
56
- matches.push(package)
57
- end
54
+ matches = []
55
+ packages.each do |package|
56
+ if package.name === name && (version.nil? || version === package.version)
57
+ matches.push package
58
58
  end
59
- matches
59
+ end
60
+ matches
60
61
  end
61
62
 
63
+ ##
64
+ # Searches the repository for packages containing the query
65
+ #
66
+ # @param query string
67
+ # The search query
68
+ # @param mode int
69
+ # A set of SEARCH_* constants to search on, implementations should do a best effort only
70
+ #
71
+ # @return array[] an array of array('name' => '...', 'description' => '...')
72
+ ##
62
73
  def search(query, mode = 0)
74
+
63
75
  regex = /(?:#{query.split(/\s+/).join('|')})/i
76
+
64
77
  matches = {}
65
78
  packages.each do |package|
79
+
66
80
  name = package.name
67
81
 
68
- # already matched
82
+ # skip if already matched
69
83
  next if matches[name]
70
84
 
71
85
  # search
72
- unless regex.match(name)
73
- unless mode === Composer::Repository::BaseRepository::SEARCH_FULLTEXT &&
74
- package.instance_of?(Composer::Package::CompletePackage) &&
75
- regex.match("#{package.keywords ? package.keywords.join(' ') : ''} #{package.description ? package.description : ''}")
76
- next
77
- end
86
+ if regex.match(name) ||
87
+ mode === ::Composer::Repository::BaseRepository::SEARCH_FULLTEXT &&
88
+ package.kind_of?(::Composer::Package::CompletePackage) &&
89
+ regex.match("#{package.keywords ? package.keywords.join(' ') : ''} #{package.description ? package.description : ''}")
90
+
91
+ matches[name] = {
92
+ 'name' => package.pretty_name,
93
+ 'description' => package.send('description'),
94
+ }
78
95
  end
79
-
80
- matches[name] = {
81
- 'name' => package.pretty_name,
82
- 'description' => package.description,
83
- }
84
-
85
96
  end
86
97
  matches.values
87
98
  end
@@ -91,7 +102,7 @@ module Composer
91
102
  raise ArgumentError,
92
103
  'package must be specified'
93
104
  end
94
- unless package.is_a?(Composer::Package::BasePackage)
105
+ unless package.is_a?(::Composer::Package::Package)
95
106
  raise TypeError,
96
107
  'package must be a class or superclass of \
97
108
  Composer::Package::Package'
@@ -105,16 +116,18 @@ module Composer
105
116
  false
106
117
  end
107
118
 
119
+ ##
108
120
  # Adds a new package to the repository
109
121
  #
110
- # Params:
111
- # +package+ Package The package to add
122
+ # @param package Composer::Package::Package
123
+ # The package to add
124
+ ##
112
125
  def add_package(package)
113
126
  unless package
114
127
  raise ArgumentError,
115
128
  'package must be specified'
116
129
  end
117
- unless package.is_a?(Composer::Package::BasePackage)
130
+ unless package.is_a?(::Composer::Package::Package)
118
131
  raise TypeError,
119
132
  'package must be a class or superclass of \
120
133
  Composer::Package::Package'
@@ -126,7 +139,7 @@ module Composer
126
139
 
127
140
  @packages << package
128
141
 
129
- if package.instance_of?(Composer::Package::AliasPackage)
142
+ if package.instance_of?(::Composer::Package::AliasPackage)
130
143
  aliased_package = package.alias_of
131
144
  if aliased_package.repository === nil
132
145
  add_package(aliased_package)
@@ -134,16 +147,18 @@ module Composer
134
147
  end
135
148
  end
136
149
 
150
+ ##
137
151
  # Removes package from repository.
138
152
  #
139
- # Params:
140
- # +package+ package instance to remove
153
+ # @param package Composer::Package::Package
154
+ # The package instance to remove
155
+ ##
141
156
  def remove_package(package)
142
157
  unless package
143
158
  raise ArgumentError,
144
159
  'package must be specified'
145
160
  end
146
- unless package.is_a?(Composer::Package::BasePackage)
161
+ unless package.is_a?(::Composer::Package::Package)
147
162
  raise TypeError,
148
163
  'package must be a class or superclass of \
149
164
  Composer::Package::Package'
@@ -155,7 +170,7 @@ module Composer
155
170
  packages.each do |repo_package|
156
171
  if repo_package.unique_name === package_id
157
172
  @packages.delete_at(index)
158
- return
173
+ break
159
174
  end
160
175
  index = index + 1
161
176
  end
@@ -167,24 +182,26 @@ module Composer
167
182
  end
168
183
 
169
184
  def count
170
- @packages.length
185
+ packages.length
171
186
  end
172
187
 
173
188
  protected
174
189
 
190
+ ##
175
191
  # Initializes the packages array.
176
192
  # Mostly meant as an extension point.
193
+ ##
177
194
  def initialize_repository
178
195
  @packages = []
179
196
  end
180
197
 
181
198
  def create_alias_package(package, version, pretty_version)
182
- if package.instance_of?(Composer::Package::AliasPackage)
199
+ if package.instance_of?(::Composer::Package::AliasPackage)
183
200
  alias_of = package.alias_of
184
201
  else
185
202
  alias_of = package
186
203
  end
187
- Composer::Package::AliasPackage.new(
204
+ ::Composer::Package::AliasPackage.new(
188
205
  alias_of,
189
206
  version,
190
207
  pretty_version