php-composer 0.4.5 → 1.0.0.pre.alpha11

Sign up to get free protection for your applications and to get access to all the features.
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