php-composer 0.1.1 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +10 -10
- data/Gemfile +15 -15
- data/LICENSE.txt +21 -21
- data/README.md +35 -35
- data/Rakefile +1 -1
- data/lib/composer.rb +52 -52
- data/lib/composer/error.rb +8 -8
- data/lib/composer/json/json_file.rb +270 -270
- data/lib/composer/package/alias_package.rb +273 -273
- data/lib/composer/package/base_package.rb +130 -130
- data/lib/composer/package/complete_package.rb +55 -55
- data/lib/composer/package/dumper/hash_dumper.rb +169 -169
- data/lib/composer/package/link.rb +51 -51
- data/lib/composer/package/link_constraint/base_constraint.rb +35 -35
- data/lib/composer/package/link_constraint/empty_constraint.rb +34 -34
- data/lib/composer/package/link_constraint/multi_constraint.rb +66 -66
- data/lib/composer/package/link_constraint/specific_constraint.rb +40 -40
- data/lib/composer/package/link_constraint/version_constraint.rb +220 -220
- data/lib/composer/package/loader/hash_loader.rb +316 -316
- data/lib/composer/package/loader/json_loader.rb +47 -47
- data/lib/composer/package/loader/project_attributes_loader.rb +71 -71
- data/lib/composer/package/loader/project_root_package_loader.rb +28 -28
- data/lib/composer/package/package.rb +118 -118
- data/lib/composer/package/root_alias_package.rb +37 -37
- data/lib/composer/package/root_package.rb +37 -37
- data/lib/composer/package/version/version_parser.rb +583 -583
- data/lib/composer/package/version/version_selector.rb +106 -106
- data/lib/composer/repository/filesystem_repository.rb +84 -85
- data/lib/composer/repository/{array_repository.rb → hash_repository.rb} +195 -195
- data/lib/composer/repository/{writeable_array_repository.rb → writeable_hash_repository.rb} +57 -59
- data/lib/composer/version.rb +3 -3
- data/php-composer.gemspec +31 -31
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8241ec13c67744cf1fd4170eb39936928677f4da
|
4
|
+
data.tar.gz: e24e4001f8e93ec75d30683a86118dc861010a8e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c7e2fde5ee0935285a1a968957a39319bf010910e35c5d51559b7306a2df67314534af2313cf725742b79ab4125093d70f94149d2d346384c226f05540564467
|
7
|
+
data.tar.gz: 2ffa1805e88423b8385f15e0562b8e183bfe6a0e4796e27359853998131a9731ae62332edd0a410260f2d6a8b4de3e33a00e3880b0c17a872e294e0643da32a8
|
data/.gitignore
CHANGED
@@ -1,10 +1,10 @@
|
|
1
|
-
/.bundle/
|
2
|
-
/.idea/
|
3
|
-
/.yardoc
|
4
|
-
/Gemfile.lock
|
5
|
-
/_yardoc/
|
6
|
-
/coverage/
|
7
|
-
/doc/
|
8
|
-
/pkg/
|
9
|
-
/spec/reports/
|
10
|
-
/tmp/
|
1
|
+
/.bundle/
|
2
|
+
/.idea/
|
3
|
+
/.yardoc
|
4
|
+
/Gemfile.lock
|
5
|
+
/_yardoc/
|
6
|
+
/coverage/
|
7
|
+
/doc/
|
8
|
+
/pkg/
|
9
|
+
/spec/reports/
|
10
|
+
/tmp/
|
data/Gemfile
CHANGED
@@ -1,15 +1,15 @@
|
|
1
|
-
source 'https://rubygems.org'
|
2
|
-
|
3
|
-
# Specify your gem's dependencies in composer.gemspec
|
4
|
-
gemspec
|
5
|
-
|
6
|
-
gem 'json', '>= 1.7', :platforms => [:mri_18, :mri_19]
|
7
|
-
gem 'json-schema', '>= 2.5.0'
|
8
|
-
# gem 'version_compare', '~> 0.0.2'
|
9
|
-
gem 'digest-crc'
|
10
|
-
|
11
|
-
group :development, :test do
|
12
|
-
gem 'rubocop', '>= 0.28.0', require: false
|
13
|
-
gem 'rspec'
|
14
|
-
gem 'simplecov', '>= 0.9.2'
|
15
|
-
end
|
1
|
+
source 'https://rubygems.org'
|
2
|
+
|
3
|
+
# Specify your gem's dependencies in composer.gemspec
|
4
|
+
gemspec
|
5
|
+
|
6
|
+
gem 'json', '>= 1.7', :platforms => [:mri_18, :mri_19]
|
7
|
+
gem 'json-schema', '>= 2.5.0'
|
8
|
+
# gem 'version_compare', '~> 0.0.2'
|
9
|
+
gem 'digest-crc'
|
10
|
+
|
11
|
+
group :development, :test do
|
12
|
+
gem 'rubocop', '>= 0.28.0', require: false
|
13
|
+
gem 'rspec'
|
14
|
+
gem 'simplecov', '>= 0.9.2'
|
15
|
+
end
|
data/LICENSE.txt
CHANGED
@@ -1,21 +1,21 @@
|
|
1
|
-
The MIT License (MIT)
|
2
|
-
|
3
|
-
Copyright (c) 2015, Ioannis Kappas <ikappas@devworks.gr>
|
4
|
-
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
7
|
-
in the Software without restriction, including without limitation the rights
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
10
|
-
furnished to do so, subject to the following conditions:
|
11
|
-
|
12
|
-
The above copyright notice and this permission notice shall be included in
|
13
|
-
all copies or substantial portions of the Software.
|
14
|
-
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
-
THE SOFTWARE.
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2015, Ioannis Kappas <ikappas@devworks.gr>
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
CHANGED
@@ -1,35 +1,35 @@
|
|
1
|
-
# PHP Composer Ruby Gem
|
2
|
-
|
3
|
-
A ruby gem library for consistent interactions with php composer dependency manager.
|
4
|
-
|
5
|
-
This is a partial port of the [Composer - Dependency Management for PHP](https://github.com/composer/composer) project as a library that enables consistent interactions with php composer.
|
6
|
-
|
7
|
-
See [https://getcomposer.org/](https://getcomposer.org/) for more information.
|
8
|
-
|
9
|
-
## Installation / Usage
|
10
|
-
Add this line to your application's Gemfile:
|
11
|
-
|
12
|
-
```ruby
|
13
|
-
gem 'php-composer'
|
14
|
-
```
|
15
|
-
|
16
|
-
And then execute:
|
17
|
-
|
18
|
-
$ bundle
|
19
|
-
|
20
|
-
Or install it yourself as:
|
21
|
-
|
22
|
-
$ gem install php-composer
|
23
|
-
|
24
|
-
## Authors
|
25
|
-
Ioannis Kappas - <ikappas@devworks.gr>
|
26
|
-
|
27
|
-
## License
|
28
|
-
PHP Composer Ruby Gem is licensed under the MIT License - see the LICENSE file for details
|
29
|
-
|
30
|
-
## Contributing
|
31
|
-
1. Fork it ( https://github.com/ikappas/php-composer/fork )
|
32
|
-
2. Create your feature branch (`git checkout -b my-new-feature`)
|
33
|
-
3. Commit your changes (`git commit -am 'Add some feature'`)
|
34
|
-
4. Push to the branch (`git push origin my-new-feature`)
|
35
|
-
5. Create a new Pull Request
|
1
|
+
# PHP Composer Ruby Gem
|
2
|
+
|
3
|
+
A ruby gem library for consistent interactions with php composer dependency manager.
|
4
|
+
|
5
|
+
This is a partial port of the [Composer - Dependency Management for PHP](https://github.com/composer/composer) project as a library that enables consistent interactions with php composer.
|
6
|
+
|
7
|
+
See [https://getcomposer.org/](https://getcomposer.org/) for more information.
|
8
|
+
|
9
|
+
## Installation / Usage
|
10
|
+
Add this line to your application's Gemfile:
|
11
|
+
|
12
|
+
```ruby
|
13
|
+
gem 'php-composer'
|
14
|
+
```
|
15
|
+
|
16
|
+
And then execute:
|
17
|
+
|
18
|
+
$ bundle
|
19
|
+
|
20
|
+
Or install it yourself as:
|
21
|
+
|
22
|
+
$ gem install php-composer
|
23
|
+
|
24
|
+
## Authors
|
25
|
+
Ioannis Kappas - <ikappas@devworks.gr>
|
26
|
+
|
27
|
+
## License
|
28
|
+
PHP Composer Ruby Gem is licensed under the MIT License - see the LICENSE file for details
|
29
|
+
|
30
|
+
## Contributing
|
31
|
+
1. Fork it ( https://github.com/ikappas/php-composer/fork )
|
32
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
33
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
34
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
35
|
+
5. Create a new Pull Request
|
data/Rakefile
CHANGED
@@ -1 +1 @@
|
|
1
|
-
require 'bundler/gem_tasks'
|
1
|
+
require 'bundler/gem_tasks'
|
data/lib/composer.rb
CHANGED
@@ -1,52 +1,52 @@
|
|
1
|
-
# external
|
2
|
-
require 'json'
|
3
|
-
require 'json-schema'
|
4
|
-
|
5
|
-
# /
|
6
|
-
require 'composer/version'
|
7
|
-
require 'composer/error'
|
8
|
-
|
9
|
-
# /json
|
10
|
-
require 'composer/json/json_validaton_error'
|
11
|
-
require 'composer/json/json_file'
|
12
|
-
require 'composer/json/json_formatter'
|
13
|
-
|
14
|
-
# /package
|
15
|
-
require 'composer/package/base_package'
|
16
|
-
require 'composer/package/package'
|
17
|
-
require 'composer/package/complete_package'
|
18
|
-
require 'composer/package/alias_package'
|
19
|
-
require 'composer/package/root_alias_package'
|
20
|
-
require 'composer/package/root_package'
|
21
|
-
require 'composer/package/link'
|
22
|
-
|
23
|
-
# /package/dumper
|
24
|
-
require 'composer/package/dumper/hash_dumper'
|
25
|
-
|
26
|
-
# /package/link_constraint
|
27
|
-
require 'composer/package/link_constraint/base_constraint'
|
28
|
-
require 'composer/package/link_constraint/empty_constraint'
|
29
|
-
require 'composer/package/link_constraint/specific_constraint'
|
30
|
-
require 'composer/package/link_constraint/version_constraint'
|
31
|
-
require 'composer/package/link_constraint/multi_constraint'
|
32
|
-
|
33
|
-
# /package/loader
|
34
|
-
require 'composer/package/loader/hash_loader'
|
35
|
-
require 'composer/package/loader/json_loader'
|
36
|
-
|
37
|
-
# /package/version
|
38
|
-
require 'composer/package/version/version_parser'
|
39
|
-
require 'composer/package/version/version_selector'
|
40
|
-
|
41
|
-
# Dir[File.join(File.dirname(__FILE__), "composer/package/dumper/*.rb")].each {|file| require file }
|
42
|
-
# Dir[File.join(File.dirname(__FILE__), "composer/package/link_constraint/*.rb")].each {|file| require file }
|
43
|
-
# Dir[File.join(File.dirname(__FILE__), "composer/package/loader/*.rb")].each {|file| require file }
|
44
|
-
# Dir[File.join(File.dirname(__FILE__), "composer/package/version/*.rb")].each {|file| require file }
|
45
|
-
|
46
|
-
# /repository
|
47
|
-
require 'composer/repository/
|
48
|
-
require 'composer/repository/
|
49
|
-
require 'composer/repository/filesystem_repository'
|
50
|
-
|
51
|
-
module Composer
|
52
|
-
end
|
1
|
+
# external
|
2
|
+
require 'json'
|
3
|
+
require 'json-schema'
|
4
|
+
|
5
|
+
# /
|
6
|
+
require 'composer/version'
|
7
|
+
require 'composer/error'
|
8
|
+
|
9
|
+
# /json
|
10
|
+
require 'composer/json/json_validaton_error'
|
11
|
+
require 'composer/json/json_file'
|
12
|
+
require 'composer/json/json_formatter'
|
13
|
+
|
14
|
+
# /package
|
15
|
+
require 'composer/package/base_package'
|
16
|
+
require 'composer/package/package'
|
17
|
+
require 'composer/package/complete_package'
|
18
|
+
require 'composer/package/alias_package'
|
19
|
+
require 'composer/package/root_alias_package'
|
20
|
+
require 'composer/package/root_package'
|
21
|
+
require 'composer/package/link'
|
22
|
+
|
23
|
+
# /package/dumper
|
24
|
+
require 'composer/package/dumper/hash_dumper'
|
25
|
+
|
26
|
+
# /package/link_constraint
|
27
|
+
require 'composer/package/link_constraint/base_constraint'
|
28
|
+
require 'composer/package/link_constraint/empty_constraint'
|
29
|
+
require 'composer/package/link_constraint/specific_constraint'
|
30
|
+
require 'composer/package/link_constraint/version_constraint'
|
31
|
+
require 'composer/package/link_constraint/multi_constraint'
|
32
|
+
|
33
|
+
# /package/loader
|
34
|
+
require 'composer/package/loader/hash_loader'
|
35
|
+
require 'composer/package/loader/json_loader'
|
36
|
+
|
37
|
+
# /package/version
|
38
|
+
require 'composer/package/version/version_parser'
|
39
|
+
require 'composer/package/version/version_selector'
|
40
|
+
|
41
|
+
# Dir[File.join(File.dirname(__FILE__), "composer/package/dumper/*.rb")].each {|file| require file }
|
42
|
+
# Dir[File.join(File.dirname(__FILE__), "composer/package/link_constraint/*.rb")].each {|file| require file }
|
43
|
+
# Dir[File.join(File.dirname(__FILE__), "composer/package/loader/*.rb")].each {|file| require file }
|
44
|
+
# Dir[File.join(File.dirname(__FILE__), "composer/package/version/*.rb")].each {|file| require file }
|
45
|
+
|
46
|
+
# /repository
|
47
|
+
require 'composer/repository/hash_repository'
|
48
|
+
require 'composer/repository/writeable_hash_repository'
|
49
|
+
require 'composer/repository/filesystem_repository'
|
50
|
+
|
51
|
+
module Composer
|
52
|
+
end
|
data/lib/composer/error.rb
CHANGED
@@ -1,8 +1,8 @@
|
|
1
|
-
module Composer
|
2
|
-
class Error < ::StandardError; end
|
3
|
-
class ArgumentError < Error; end
|
4
|
-
class TypeError < Error; end
|
5
|
-
class UnexpectedValueError < Error; end
|
6
|
-
class LogicError < Error; end
|
7
|
-
class InvalidRepositoryError < Error; end
|
8
|
-
end
|
1
|
+
module Composer
|
2
|
+
class Error < ::StandardError; end
|
3
|
+
class ArgumentError < Error; end
|
4
|
+
class TypeError < Error; end
|
5
|
+
class UnexpectedValueError < Error; end
|
6
|
+
class LogicError < Error; end
|
7
|
+
class InvalidRepositoryError < Error; end
|
8
|
+
end
|
@@ -1,270 +1,270 @@
|
|
1
|
-
#
|
2
|
-
# This file was ported to ruby from Composer php source code file.
|
3
|
-
# Original Source: Composer\Json\JsonFile.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 Json
|
14
|
-
# Reads/writes json files.
|
15
|
-
#
|
16
|
-
# PHP Authors:
|
17
|
-
# Konstantin Kudryashiv <ever.zet@gmail.com>
|
18
|
-
# Jordi Boggiano <j.boggiano@seld.be>
|
19
|
-
#
|
20
|
-
# Ruby Authors:
|
21
|
-
# Ioannis Kappas <ikappas@devworks.gr>
|
22
|
-
class JsonFile
|
23
|
-
attr_reader :path
|
24
|
-
|
25
|
-
LAX_SCHEMA = 1
|
26
|
-
STRICT_SCHEMA = 2
|
27
|
-
|
28
|
-
JSON_ERROR_NONE = 0
|
29
|
-
JSON_ERROR_DEPTH = 1
|
30
|
-
JSON_ERROR_STATE_MISMATCH = 2
|
31
|
-
JSON_ERROR_CTRL_CHAR = 3
|
32
|
-
JSON_ERROR_SYNTAX = 4
|
33
|
-
JSON_ERROR_UTF8 = 5
|
34
|
-
JSON_ERROR_RECURSION = 6
|
35
|
-
JSON_ERROR_INF_OR_NAN = 7
|
36
|
-
JSON_ERROR_UNSUPPORTED_TYPE = 8
|
37
|
-
|
38
|
-
# Initializes json file reader/parser.
|
39
|
-
# @param [String] path path to a json file
|
40
|
-
# @param [RemoteFileSystem] rfs The remote filesystem to use for http/https json files
|
41
|
-
# @raise [ArgumentError]
|
42
|
-
def initialize(path, rfs = nil)
|
43
|
-
@path = path
|
44
|
-
if rfs === nil && /^https?:\/\//i.match(path)
|
45
|
-
raise ArgumentError,
|
46
|
-
'http urls require a RemoteFilesystem instance to be passed'
|
47
|
-
end
|
48
|
-
@rfs = rfs
|
49
|
-
end
|
50
|
-
|
51
|
-
# Checks whether this json file exists.
|
52
|
-
#
|
53
|
-
# Returns:
|
54
|
-
# true if this json file exists; otherwise false.
|
55
|
-
def exist?
|
56
|
-
File.exist?(path)
|
57
|
-
end
|
58
|
-
|
59
|
-
# Reads the json file.
|
60
|
-
#
|
61
|
-
# Raises:
|
62
|
-
# RuntimeError
|
63
|
-
#
|
64
|
-
# Returns:
|
65
|
-
# mixed
|
66
|
-
def read
|
67
|
-
if @rfs
|
68
|
-
json = @rfs.get_contents(@path, @path, false)
|
69
|
-
else
|
70
|
-
json = File.open(@path, 'r') { |f| f.read }
|
71
|
-
end
|
72
|
-
|
73
|
-
parse_json(json, @path)
|
74
|
-
|
75
|
-
rescue Exception => e
|
76
|
-
raise e
|
77
|
-
end
|
78
|
-
|
79
|
-
def write(hash, options = 448)
|
80
|
-
dir = File.dirname(@path)
|
81
|
-
|
82
|
-
unless File.directory?(storage_path)
|
83
|
-
if File.exist?(dir)
|
84
|
-
raise UnexpectedValueError,
|
85
|
-
"#{dir} exists and is not a directory."
|
86
|
-
end
|
87
|
-
FileUtils.mkdir_p(dir, 0777)
|
88
|
-
end
|
89
|
-
|
90
|
-
retries = 3
|
91
|
-
while retries >= 0
|
92
|
-
begin
|
93
|
-
file_ending = options & JSON_PRETTY_PRINT ? "\n" : ''
|
94
|
-
File.open(path, 'w') do |f|
|
95
|
-
content = encode(hash, options) + file_ending
|
96
|
-
f.write(content)
|
97
|
-
end
|
98
|
-
break
|
99
|
-
|
100
|
-
rescue Exception => e
|
101
|
-
if retries
|
102
|
-
retries -= 1
|
103
|
-
sleep 0.5
|
104
|
-
else
|
105
|
-
raise e
|
106
|
-
end
|
107
|
-
end
|
108
|
-
end
|
109
|
-
|
110
|
-
end
|
111
|
-
|
112
|
-
# Validates the schema of the current json file according
|
113
|
-
# to composer-schema.json rules
|
114
|
-
#
|
115
|
-
# @param schema int a JsonFile::*_SCHEMA constant
|
116
|
-
# @return bool true if schema is valid; Otherwise false.
|
117
|
-
# @throw Composer::Json::JsonValidationError
|
118
|
-
def validate_schema(schema = STRICT_SCHEMA)
|
119
|
-
content = File.open(@path, 'r') { |f| f.read }
|
120
|
-
data = JSON.parse(content)
|
121
|
-
|
122
|
-
if data == nil && content != 'null'
|
123
|
-
self::validate_syntax(content, @path)
|
124
|
-
end
|
125
|
-
|
126
|
-
schema_file = File.join(
|
127
|
-
File.dirname(__FILE__),
|
128
|
-
'../../../resources/composer-schema.json'
|
129
|
-
)
|
130
|
-
|
131
|
-
schema_data = JSON.parse(
|
132
|
-
File.open(schema_file, 'r') { |f| f.read }
|
133
|
-
)
|
134
|
-
|
135
|
-
if schema === LAX_SCHEMA
|
136
|
-
schema_data['additionalProperties'] = true
|
137
|
-
schema_data['properties']['name']['required'] = false
|
138
|
-
schema_data['properties']['description']['required'] = false
|
139
|
-
end
|
140
|
-
|
141
|
-
errors = JSON::Validator.fully_validate(
|
142
|
-
schema_data,
|
143
|
-
data,
|
144
|
-
{:errors_as_objects => true}
|
145
|
-
)
|
146
|
-
|
147
|
-
unless errors.empty?
|
148
|
-
processed_errors = []
|
149
|
-
errors.each do |error|
|
150
|
-
prefix = error[:fragment] ? "#{error[:fragment]} : " : ''
|
151
|
-
processed_errors.push( prefix + error[:message])
|
152
|
-
end
|
153
|
-
raise Composer::Json::JsonValidationError.new(processed_errors),
|
154
|
-
"\"#{@path}\" does not match the expected JSON schema"
|
155
|
-
end
|
156
|
-
|
157
|
-
true
|
158
|
-
end
|
159
|
-
|
160
|
-
class << self
|
161
|
-
|
162
|
-
# Encodes an hash into (optionally pretty-printed) JSON
|
163
|
-
#
|
164
|
-
# @param data mixed Data to encode into a formatted JSON string
|
165
|
-
# @param options int json_encode options (defaults to JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE)
|
166
|
-
# @return string Encoded json
|
167
|
-
def encode(data, options = 448)
|
168
|
-
|
169
|
-
# if (version_compare(PHP_VERSION, '5.4', '>=')) {
|
170
|
-
# $json = json_encode(data, options);
|
171
|
-
|
172
|
-
# # compact brackets to follow recent php versions
|
173
|
-
# if (PHP_VERSION_ID < 50428 || (PHP_VERSION_ID >= 50500 && PHP_VERSION_ID < 50512) || (defined('JSON_C_VERSION') && version_compare(phpversion('json'), '1.3.6', '<'))) {
|
174
|
-
# $json = preg_replace('/\[\s+\]/', '[]', $json);
|
175
|
-
# $json = preg_replace('/\{\s+\}/', '{}', $json);
|
176
|
-
# }
|
177
|
-
|
178
|
-
# return $json;
|
179
|
-
# }
|
180
|
-
|
181
|
-
# * *indent*: a string used to indent levels (default: ''),
|
182
|
-
# * *space*: a string that is put after, a : or , delimiter (default: ''),
|
183
|
-
# * *space_before*: a string that is put before a : pair delimiter (default: ''),
|
184
|
-
# * *object_nl*: a string that is put at the end of a JSON object (default: ''),
|
185
|
-
# * *array_nl*: a string that is put at the end of a JSON array (default: ''),
|
186
|
-
# * *allow_nan*: true if NaN, Infinity, and -Infinity should be
|
187
|
-
# generated, otherwise an exception is thrown if these values are
|
188
|
-
# encountered. This options defaults to false.
|
189
|
-
# * *max_nesting*: The maximum depth of nesting allowed in the data
|
190
|
-
# structures from which JSON is to be generated. Disable depth checking
|
191
|
-
# with :max_nesting => false, it defaults to 100.
|
192
|
-
|
193
|
-
if data.nil?
|
194
|
-
return 'null'
|
195
|
-
elsif data.is_a?(TrueClass)
|
196
|
-
return 'true'
|
197
|
-
elsif data.is_a?(FalseClass)
|
198
|
-
return 'false'
|
199
|
-
elsif data.is_a?(Integer)
|
200
|
-
return Integer(data)
|
201
|
-
elsif data.is_a?(Float)
|
202
|
-
return Float(data)
|
203
|
-
else
|
204
|
-
begin
|
205
|
-
json = JSON.generate(data, { quirks_mode: false })
|
206
|
-
rescue JSON::GeneratorError => e
|
207
|
-
if e.message === 'only generation of JSON objects or arrays allowed'
|
208
|
-
#trick into parsing scalar values by wrapping them in an array
|
209
|
-
scalar = data.gsub("\\\\", "\\\\\\")
|
210
|
-
if json = JSON::generate([scalar])
|
211
|
-
json = json[1..(json.length - 2)]
|
212
|
-
end
|
213
|
-
end
|
214
|
-
end
|
215
|
-
end
|
216
|
-
|
217
|
-
return json unless options
|
218
|
-
|
219
|
-
result = Composer::Json::JsonFormatter::format(
|
220
|
-
json,
|
221
|
-
options
|
222
|
-
)
|
223
|
-
|
224
|
-
result
|
225
|
-
end
|
226
|
-
|
227
|
-
# Parses json string and returns hash.
|
228
|
-
#
|
229
|
-
# Params:
|
230
|
-
# +json+ string The json string to parse
|
231
|
-
# +file+ string The json file
|
232
|
-
#
|
233
|
-
# Returns:
|
234
|
-
# mixed
|
235
|
-
def parse_json(json, file = nil)
|
236
|
-
last_error = JSON_ERROR_NONE
|
237
|
-
|
238
|
-
begin
|
239
|
-
data = JSON.parse(json)
|
240
|
-
rescue Exception => e
|
241
|
-
last_error = e
|
242
|
-
end
|
243
|
-
|
244
|
-
if data.nil? && last_error != JSON_ERROR_NONE
|
245
|
-
validate_syntax(json, file)
|
246
|
-
raise JSON::ParserError,
|
247
|
-
"\"#{file}\" does not contain valid JSON\n
|
248
|
-
#{last_error.message}"
|
249
|
-
end
|
250
|
-
|
251
|
-
data
|
252
|
-
end
|
253
|
-
|
254
|
-
def validate_syntax(json, file)
|
255
|
-
# JSON::
|
256
|
-
# parser = Composer::Json::JsonParser.new
|
257
|
-
# if (result = parser.lint(json))
|
258
|
-
# raise ParsingError,
|
259
|
-
# "\"#{file}\" does not contain valid JSON\n
|
260
|
-
# #{result.message}"
|
261
|
-
# end
|
262
|
-
# if (defined('JSON_ERROR_UTF8') && JSON_ERROR_UTF8 === json_last_error()) {
|
263
|
-
# throw new \UnexpectedValueException('"'.$file.'" is not UTF-8, could not parse as JSON');
|
264
|
-
# }
|
265
|
-
true
|
266
|
-
end
|
267
|
-
end
|
268
|
-
end
|
269
|
-
end
|
270
|
-
end
|
1
|
+
#
|
2
|
+
# This file was ported to ruby from Composer php source code file.
|
3
|
+
# Original Source: Composer\Json\JsonFile.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 Json
|
14
|
+
# Reads/writes json files.
|
15
|
+
#
|
16
|
+
# PHP Authors:
|
17
|
+
# Konstantin Kudryashiv <ever.zet@gmail.com>
|
18
|
+
# Jordi Boggiano <j.boggiano@seld.be>
|
19
|
+
#
|
20
|
+
# Ruby Authors:
|
21
|
+
# Ioannis Kappas <ikappas@devworks.gr>
|
22
|
+
class JsonFile
|
23
|
+
attr_reader :path
|
24
|
+
|
25
|
+
LAX_SCHEMA = 1
|
26
|
+
STRICT_SCHEMA = 2
|
27
|
+
|
28
|
+
JSON_ERROR_NONE = 0
|
29
|
+
JSON_ERROR_DEPTH = 1
|
30
|
+
JSON_ERROR_STATE_MISMATCH = 2
|
31
|
+
JSON_ERROR_CTRL_CHAR = 3
|
32
|
+
JSON_ERROR_SYNTAX = 4
|
33
|
+
JSON_ERROR_UTF8 = 5
|
34
|
+
JSON_ERROR_RECURSION = 6
|
35
|
+
JSON_ERROR_INF_OR_NAN = 7
|
36
|
+
JSON_ERROR_UNSUPPORTED_TYPE = 8
|
37
|
+
|
38
|
+
# Initializes json file reader/parser.
|
39
|
+
# @param [String] path path to a json file
|
40
|
+
# @param [RemoteFileSystem] rfs The remote filesystem to use for http/https json files
|
41
|
+
# @raise [ArgumentError]
|
42
|
+
def initialize(path, rfs = nil)
|
43
|
+
@path = path
|
44
|
+
if rfs === nil && /^https?:\/\//i.match(path)
|
45
|
+
raise ArgumentError,
|
46
|
+
'http urls require a RemoteFilesystem instance to be passed'
|
47
|
+
end
|
48
|
+
@rfs = rfs
|
49
|
+
end
|
50
|
+
|
51
|
+
# Checks whether this json file exists.
|
52
|
+
#
|
53
|
+
# Returns:
|
54
|
+
# true if this json file exists; otherwise false.
|
55
|
+
def exist?
|
56
|
+
File.exist?(path)
|
57
|
+
end
|
58
|
+
|
59
|
+
# Reads the json file.
|
60
|
+
#
|
61
|
+
# Raises:
|
62
|
+
# RuntimeError
|
63
|
+
#
|
64
|
+
# Returns:
|
65
|
+
# mixed
|
66
|
+
def read
|
67
|
+
if @rfs
|
68
|
+
json = @rfs.get_contents(@path, @path, false)
|
69
|
+
else
|
70
|
+
json = File.open(@path, 'r') { |f| f.read }
|
71
|
+
end
|
72
|
+
|
73
|
+
parse_json(json, @path)
|
74
|
+
|
75
|
+
rescue Exception => e
|
76
|
+
raise e
|
77
|
+
end
|
78
|
+
|
79
|
+
def write(hash, options = 448)
|
80
|
+
dir = File.dirname(@path)
|
81
|
+
|
82
|
+
unless File.directory?(storage_path)
|
83
|
+
if File.exist?(dir)
|
84
|
+
raise UnexpectedValueError,
|
85
|
+
"#{dir} exists and is not a directory."
|
86
|
+
end
|
87
|
+
FileUtils.mkdir_p(dir, 0777)
|
88
|
+
end
|
89
|
+
|
90
|
+
retries = 3
|
91
|
+
while retries >= 0
|
92
|
+
begin
|
93
|
+
file_ending = options & JSON_PRETTY_PRINT ? "\n" : ''
|
94
|
+
File.open(path, 'w') do |f|
|
95
|
+
content = encode(hash, options) + file_ending
|
96
|
+
f.write(content)
|
97
|
+
end
|
98
|
+
break
|
99
|
+
|
100
|
+
rescue Exception => e
|
101
|
+
if retries
|
102
|
+
retries -= 1
|
103
|
+
sleep 0.5
|
104
|
+
else
|
105
|
+
raise e
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
end
|
111
|
+
|
112
|
+
# Validates the schema of the current json file according
|
113
|
+
# to composer-schema.json rules
|
114
|
+
#
|
115
|
+
# @param schema int a JsonFile::*_SCHEMA constant
|
116
|
+
# @return bool true if schema is valid; Otherwise false.
|
117
|
+
# @throw Composer::Json::JsonValidationError
|
118
|
+
def validate_schema(schema = STRICT_SCHEMA)
|
119
|
+
content = File.open(@path, 'r') { |f| f.read }
|
120
|
+
data = JSON.parse(content)
|
121
|
+
|
122
|
+
if data == nil && content != 'null'
|
123
|
+
self::validate_syntax(content, @path)
|
124
|
+
end
|
125
|
+
|
126
|
+
schema_file = File.join(
|
127
|
+
File.dirname(__FILE__),
|
128
|
+
'../../../resources/composer-schema.json'
|
129
|
+
)
|
130
|
+
|
131
|
+
schema_data = JSON.parse(
|
132
|
+
File.open(schema_file, 'r') { |f| f.read }
|
133
|
+
)
|
134
|
+
|
135
|
+
if schema === LAX_SCHEMA
|
136
|
+
schema_data['additionalProperties'] = true
|
137
|
+
schema_data['properties']['name']['required'] = false
|
138
|
+
schema_data['properties']['description']['required'] = false
|
139
|
+
end
|
140
|
+
|
141
|
+
errors = JSON::Validator.fully_validate(
|
142
|
+
schema_data,
|
143
|
+
data,
|
144
|
+
{:errors_as_objects => true}
|
145
|
+
)
|
146
|
+
|
147
|
+
unless errors.empty?
|
148
|
+
processed_errors = []
|
149
|
+
errors.each do |error|
|
150
|
+
prefix = error[:fragment] ? "#{error[:fragment]} : " : ''
|
151
|
+
processed_errors.push( prefix + error[:message])
|
152
|
+
end
|
153
|
+
raise Composer::Json::JsonValidationError.new(processed_errors),
|
154
|
+
"\"#{@path}\" does not match the expected JSON schema"
|
155
|
+
end
|
156
|
+
|
157
|
+
true
|
158
|
+
end
|
159
|
+
|
160
|
+
class << self
|
161
|
+
|
162
|
+
# Encodes an hash into (optionally pretty-printed) JSON
|
163
|
+
#
|
164
|
+
# @param data mixed Data to encode into a formatted JSON string
|
165
|
+
# @param options int json_encode options (defaults to JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE)
|
166
|
+
# @return string Encoded json
|
167
|
+
def encode(data, options = 448)
|
168
|
+
|
169
|
+
# if (version_compare(PHP_VERSION, '5.4', '>=')) {
|
170
|
+
# $json = json_encode(data, options);
|
171
|
+
|
172
|
+
# # compact brackets to follow recent php versions
|
173
|
+
# if (PHP_VERSION_ID < 50428 || (PHP_VERSION_ID >= 50500 && PHP_VERSION_ID < 50512) || (defined('JSON_C_VERSION') && version_compare(phpversion('json'), '1.3.6', '<'))) {
|
174
|
+
# $json = preg_replace('/\[\s+\]/', '[]', $json);
|
175
|
+
# $json = preg_replace('/\{\s+\}/', '{}', $json);
|
176
|
+
# }
|
177
|
+
|
178
|
+
# return $json;
|
179
|
+
# }
|
180
|
+
|
181
|
+
# * *indent*: a string used to indent levels (default: ''),
|
182
|
+
# * *space*: a string that is put after, a : or , delimiter (default: ''),
|
183
|
+
# * *space_before*: a string that is put before a : pair delimiter (default: ''),
|
184
|
+
# * *object_nl*: a string that is put at the end of a JSON object (default: ''),
|
185
|
+
# * *array_nl*: a string that is put at the end of a JSON array (default: ''),
|
186
|
+
# * *allow_nan*: true if NaN, Infinity, and -Infinity should be
|
187
|
+
# generated, otherwise an exception is thrown if these values are
|
188
|
+
# encountered. This options defaults to false.
|
189
|
+
# * *max_nesting*: The maximum depth of nesting allowed in the data
|
190
|
+
# structures from which JSON is to be generated. Disable depth checking
|
191
|
+
# with :max_nesting => false, it defaults to 100.
|
192
|
+
|
193
|
+
if data.nil?
|
194
|
+
return 'null'
|
195
|
+
elsif data.is_a?(TrueClass)
|
196
|
+
return 'true'
|
197
|
+
elsif data.is_a?(FalseClass)
|
198
|
+
return 'false'
|
199
|
+
elsif data.is_a?(Integer)
|
200
|
+
return Integer(data)
|
201
|
+
elsif data.is_a?(Float)
|
202
|
+
return Float(data)
|
203
|
+
else
|
204
|
+
begin
|
205
|
+
json = JSON.generate(data, { quirks_mode: false })
|
206
|
+
rescue JSON::GeneratorError => e
|
207
|
+
if e.message === 'only generation of JSON objects or arrays allowed'
|
208
|
+
#trick into parsing scalar values by wrapping them in an array
|
209
|
+
scalar = data.gsub("\\\\", "\\\\\\")
|
210
|
+
if json = JSON::generate([scalar])
|
211
|
+
json = json[1..(json.length - 2)]
|
212
|
+
end
|
213
|
+
end
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
217
|
+
return json unless options
|
218
|
+
|
219
|
+
result = Composer::Json::JsonFormatter::format(
|
220
|
+
json,
|
221
|
+
options
|
222
|
+
)
|
223
|
+
|
224
|
+
result
|
225
|
+
end
|
226
|
+
|
227
|
+
# Parses json string and returns hash.
|
228
|
+
#
|
229
|
+
# Params:
|
230
|
+
# +json+ string The json string to parse
|
231
|
+
# +file+ string The json file
|
232
|
+
#
|
233
|
+
# Returns:
|
234
|
+
# mixed
|
235
|
+
def parse_json(json, file = nil)
|
236
|
+
last_error = JSON_ERROR_NONE
|
237
|
+
|
238
|
+
begin
|
239
|
+
data = JSON.parse(json)
|
240
|
+
rescue Exception => e
|
241
|
+
last_error = e
|
242
|
+
end
|
243
|
+
|
244
|
+
if data.nil? && last_error != JSON_ERROR_NONE
|
245
|
+
validate_syntax(json, file)
|
246
|
+
raise JSON::ParserError,
|
247
|
+
"\"#{file}\" does not contain valid JSON\n
|
248
|
+
#{last_error.message}"
|
249
|
+
end
|
250
|
+
|
251
|
+
data
|
252
|
+
end
|
253
|
+
|
254
|
+
def validate_syntax(json, file)
|
255
|
+
# JSON::
|
256
|
+
# parser = Composer::Json::JsonParser.new
|
257
|
+
# if (result = parser.lint(json))
|
258
|
+
# raise ParsingError,
|
259
|
+
# "\"#{file}\" does not contain valid JSON\n
|
260
|
+
# #{result.message}"
|
261
|
+
# end
|
262
|
+
# if (defined('JSON_ERROR_UTF8') && JSON_ERROR_UTF8 === json_last_error()) {
|
263
|
+
# throw new \UnexpectedValueException('"'.$file.'" is not UTF-8, could not parse as JSON');
|
264
|
+
# }
|
265
|
+
true
|
266
|
+
end
|
267
|
+
end
|
268
|
+
end
|
269
|
+
end
|
270
|
+
end
|