xcop 0.6.3 → 0.7.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 +4 -4
- data/.github/workflows/rake.yml +23 -0
- data/.rubocop.yml +7 -1
- data/.rultor.yml +3 -8
- data/.simplecov +6 -6
- data/Gemfile +1 -1
- data/LICENSE.txt +1 -1
- data/README.md +30 -8
- data/Rakefile +2 -1
- data/bin/xcop +38 -10
- data/features/step_definitions/steps.rb +3 -8
- data/features/support/env.rb +1 -2
- data/lib/xcop/cli.rb +64 -0
- data/lib/xcop/document.rb +82 -0
- data/lib/xcop/rake_task.rb +35 -43
- data/lib/xcop/version.rb +3 -3
- data/test/test__helper.rb +2 -3
- data/test/{test_xcop.rb → test_document.rb} +10 -4
- data/test/test_rake_task.rb +8 -4
- data/xcop.gemspec +11 -13
- metadata +23 -30
- data/.travis.yml +0 -13
- data/appveyor.yml +0 -21
- data/lib/xcop.rb +0 -121
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 94e8fcd3843e72e2e95cc964a20acd22527734574d2da826e58b0b51fd50ead1
|
4
|
+
data.tar.gz: f454cfb06eecd4700b92c86c815bc4207d7554c455db2fba2d17a46f6c5cbc49
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 644e0b11601e49a0c8b1faf884d44d6d588d314c34e232497c9e690df6330769e3a20c0ffd975b83f9d08949599ca6c7420e0987505ddcf97b5cbdf5ff836921
|
7
|
+
data.tar.gz: 8ffdfd91e26107945987fd0914fa1debc15ab628e7020819b52d421ed21b14ca6c4a77cf12d18f614fe297d4002d2fdb7053bb94f7778a829421d3feffdad112
|
@@ -0,0 +1,23 @@
|
|
1
|
+
---
|
2
|
+
name: rake
|
3
|
+
on:
|
4
|
+
push:
|
5
|
+
branches:
|
6
|
+
- master
|
7
|
+
pull_request:
|
8
|
+
branches:
|
9
|
+
- master
|
10
|
+
jobs:
|
11
|
+
test:
|
12
|
+
strategy:
|
13
|
+
matrix:
|
14
|
+
os: [ubuntu-latest, macos-latest]
|
15
|
+
ruby: ['2.7', '3.0']
|
16
|
+
runs-on: ${{ matrix.os }}
|
17
|
+
steps:
|
18
|
+
- uses: actions/checkout@v2
|
19
|
+
- uses: ruby/setup-ruby@v1
|
20
|
+
with:
|
21
|
+
ruby-version: ${{ matrix.ruby }}
|
22
|
+
- run: bundle update
|
23
|
+
- run: bundle exec rake
|
data/.rubocop.yml
CHANGED
@@ -4,14 +4,20 @@ AllCops:
|
|
4
4
|
- 'assets/**/*'
|
5
5
|
DisplayCopNames: true
|
6
6
|
TargetRubyVersion: 2.2
|
7
|
+
NewCops: enable
|
8
|
+
SuggestExtensions: false
|
7
9
|
|
8
10
|
Metrics/CyclomaticComplexity:
|
9
11
|
Max: 10
|
10
12
|
Metrics/MethodLength:
|
11
13
|
Enabled: false
|
12
|
-
|
14
|
+
Layout/MultilineMethodCallIndentation:
|
13
15
|
Enabled: false
|
14
16
|
Metrics/AbcSize:
|
15
17
|
Enabled: false
|
16
18
|
Metrics/BlockLength:
|
17
19
|
Max: 50
|
20
|
+
Layout/EmptyLineAfterGuardClause:
|
21
|
+
Enabled: false
|
22
|
+
Style/ClassAndModuleChildren:
|
23
|
+
Enabled: false
|
data/.rultor.yml
CHANGED
@@ -1,17 +1,13 @@
|
|
1
1
|
assets:
|
2
2
|
rubygems.yml: yegor256/home#assets/rubygems.yml
|
3
3
|
install: |
|
4
|
-
|
5
|
-
|
6
|
-
sudo apt-get -y update
|
7
|
-
sudo gem install pdd -v 0.20.5
|
8
|
-
bundle install
|
4
|
+
pdd -f /dev/null
|
5
|
+
sudo bundle install --no-color "--gemfile=$(pwd)/Gemfile"
|
9
6
|
release:
|
10
7
|
script: |-
|
11
8
|
bundle exec rake
|
12
|
-
pdd -f /dev/null
|
13
9
|
rm -rf *.gem
|
14
|
-
sed -i "s/
|
10
|
+
sed -i "s/0\.0\.0/${tag}/g" lib/xcop/version.rb
|
15
11
|
git add lib/xcop/version.rb
|
16
12
|
git commit -m "version set to ${tag}"
|
17
13
|
gem build xcop.gemspec
|
@@ -20,7 +16,6 @@ release:
|
|
20
16
|
merge:
|
21
17
|
script: |-
|
22
18
|
bundle exec rake
|
23
|
-
pdd -f /dev/null
|
24
19
|
deploy:
|
25
20
|
script: |-
|
26
21
|
echo "There is nothing to deploy"
|
data/.simplecov
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright (c) 2017-
|
1
|
+
# Copyright (c) 2017-2022 Yegor Bugayenko
|
2
2
|
#
|
3
3
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
4
|
# of this software and associated documentation files (the 'Software'), to deal
|
@@ -18,21 +18,21 @@
|
|
18
18
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
19
19
|
# SOFTWARE.
|
20
20
|
|
21
|
-
if Gem.win_platform?
|
21
|
+
if Gem.win_platform?
|
22
22
|
SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter[
|
23
23
|
SimpleCov::Formatter::HTMLFormatter
|
24
24
|
]
|
25
25
|
SimpleCov.start do
|
26
|
-
add_filter
|
27
|
-
add_filter
|
26
|
+
add_filter '/test/'
|
27
|
+
add_filter '/features/'
|
28
28
|
end
|
29
29
|
else
|
30
30
|
SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter.new(
|
31
31
|
[SimpleCov::Formatter::HTMLFormatter]
|
32
32
|
)
|
33
33
|
SimpleCov.start do
|
34
|
-
add_filter
|
35
|
-
add_filter
|
34
|
+
add_filter '/test/'
|
35
|
+
add_filter '/features/'
|
36
36
|
minimum_coverage 80
|
37
37
|
end
|
38
38
|
end
|
data/Gemfile
CHANGED
data/LICENSE.txt
CHANGED
data/README.md
CHANGED
@@ -1,30 +1,31 @@
|
|
1
|
-
<img src="/logo.svg" width="64px"/>
|
1
|
+
<img alt="XCOP logo" src="/logo.svg" width="64px"/>
|
2
2
|
|
3
3
|
[](https://www.elegantobjects.org)
|
4
4
|
[](https://www.0crat.com/p/C3RFVLU72)
|
5
5
|
[](http://www.rultor.com/p/yegor256/xcop)
|
6
6
|
[](https://www.jetbrains.com/ruby/)
|
7
7
|
|
8
|
-
[](https://ci.appveyor.com/project/yegor256/xcop)
|
8
|
+
[](https://github.com/yegor256/xcop/actions/workflows/rake.yml)
|
10
9
|
[](http://www.0pdd.com/p?name=yegor256/xcop)
|
11
10
|
[](http://badge.fury.io/rb/xcop)
|
12
11
|
[](https://github.com/yegor256/xcop/blob/master/LICENSE.txt)
|
13
12
|
|
14
13
|
[](https://codeclimate.com/github/yegor256/xcop/maintainability)
|
15
14
|
[](https://codecov.io/github/yegor256/xcop?branch=master)
|
15
|
+

|
16
16
|
[](https://hitsofcode.com/view/github/yegor256/xcop)
|
17
17
|
|
18
18
|
This command line tool validates your XML files for proper formatting.
|
19
19
|
If they are not formatted correctly, it prints the difference and
|
20
|
-
|
21
|
-
if any
|
22
|
-
and 2) to format them correctly.
|
20
|
+
exits with an error. You can use it two ways: 1) to fail your build
|
21
|
+
if any XML-ish files (for example, XML, XSD, XSL, or XHTML) are not formatted correctly,
|
22
|
+
and 2) to format them correctly using `--fix` option.
|
23
23
|
|
24
|
-
Read this blog post
|
24
|
+
Read this blog post first:
|
25
25
|
[_XCOP—XML Style Checker_](https://www.yegor256.com/2017/08/29/xcop.html).
|
26
26
|
|
27
|
-
|
27
|
+
Make sure you have [Ruby installed](https://www.ruby-lang.org/en/documentation/installation/)
|
28
|
+
and then install the tool:
|
28
29
|
|
29
30
|
```bash
|
30
31
|
$ gem install xcop
|
@@ -57,6 +58,24 @@ To fix all files in the directory you can do
|
|
57
58
|
$ xcop --fix $(find . -name '*.xml')
|
58
59
|
```
|
59
60
|
|
61
|
+
## Defaults
|
62
|
+
|
63
|
+
You can put command line options into `.xcop` file in the directory
|
64
|
+
where you start `xcop`. Each option should take a single line in the file.
|
65
|
+
They all will be _added_ to the list of options you specify. For example:
|
66
|
+
|
67
|
+
```
|
68
|
+
--license LICENSE.txt
|
69
|
+
--nocolor
|
70
|
+
--quiet
|
71
|
+
--include **/*
|
72
|
+
--exclude **/*.xsl
|
73
|
+
--exclude **/*.html
|
74
|
+
```
|
75
|
+
|
76
|
+
You can also create `~/.xcop` file (in your personal home directory), which
|
77
|
+
will also be read and _added_ to the command line options.
|
78
|
+
|
60
79
|
## How to use in `Rakefile`?
|
61
80
|
|
62
81
|
This is what you need there:
|
@@ -75,6 +94,7 @@ end
|
|
75
94
|
## How to use as GitHub action?
|
76
95
|
|
77
96
|
Create new workflow file in repository under `.github/workflows/xcop.yml`:
|
97
|
+
|
78
98
|
```yaml
|
79
99
|
---
|
80
100
|
name: XCOP
|
@@ -94,7 +114,9 @@ jobs:
|
|
94
114
|
- uses: actions/checkout@v2
|
95
115
|
- uses: g4s8/xcop-action@master
|
96
116
|
```
|
117
|
+
|
97
118
|
To customize license location or files pattern use action inputs `license` and `files`:
|
119
|
+
|
98
120
|
```yaml
|
99
121
|
- uses: g4s8/xcop-action@master
|
100
122
|
with:
|
data/Rakefile
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright (c) 2017-
|
1
|
+
# Copyright (c) 2017-2022 Yegor Bugayenko
|
2
2
|
#
|
3
3
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
4
|
# of this software and associated documentation files (the 'Software'), to deal
|
@@ -56,6 +56,7 @@ desc 'Run RuboCop on all directories'
|
|
56
56
|
RuboCop::RakeTask.new(:rubocop) do |task|
|
57
57
|
task.fail_on_error = true
|
58
58
|
task.requires << 'rubocop-rspec'
|
59
|
+
task.options = ['--display-cop-names']
|
59
60
|
end
|
60
61
|
|
61
62
|
require 'cucumber/rake/task'
|
data/bin/xcop
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
-
# Copyright (c) 2017-
|
2
|
+
# Copyright (c) 2017-2022 Yegor Bugayenko
|
3
3
|
#
|
4
4
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
5
5
|
# of this software and associated documentation files (the 'Software'), to deal
|
@@ -23,21 +23,24 @@ STDOUT.sync = true
|
|
23
23
|
|
24
24
|
require 'slop'
|
25
25
|
require 'nokogiri'
|
26
|
-
|
26
|
+
require 'set'
|
27
|
+
require_relative '../lib/xcop/cli'
|
27
28
|
require_relative '../lib/xcop/version'
|
28
29
|
|
29
30
|
if Gem::Version.new(Nokogiri::VERSION) < Gem::Version.new('1.8')
|
30
31
|
puts "Nokogiri version #{Nokogiri::VERSION} is too old, 1.8+ is required"
|
31
32
|
end
|
32
33
|
|
33
|
-
|
34
|
-
|
35
|
-
|
34
|
+
def config(path)
|
35
|
+
f = File.expand_path(path)
|
36
|
+
args = []
|
37
|
+
args += File.readlines(f).map(&:strip) if File.exist?(f)
|
38
|
+
args
|
36
39
|
end
|
37
40
|
|
38
|
-
|
41
|
+
args = config('~/.xcop') + config('.xcop') + ARGV
|
39
42
|
|
40
|
-
opts = Slop.parse(
|
43
|
+
opts = Slop.parse(args, strict: true, help: true) do |o|
|
41
44
|
o.banner = "Usage (#{Xcop::VERSION}): xcop [options] [files...]"
|
42
45
|
o.bool '-h', '--help', 'Show these instructions'
|
43
46
|
o.bool '-q', '--quiet', 'Don\'t print anything if there are no errors'
|
@@ -45,6 +48,8 @@ opts = Slop.parse(merged, strict: true, help: true) do |o|
|
|
45
48
|
o.bool '--fix', 'Fix all files instead of reporting their problems'
|
46
49
|
o.bool '--nocolor', 'Suppress colored output'
|
47
50
|
o.string '--license', 'File name of the boilerplate head license'
|
51
|
+
o.array '--include', 'Glob pattern(s) to include'
|
52
|
+
o.array '--exclude', 'Glob pattern(s) to exclude'
|
48
53
|
end
|
49
54
|
|
50
55
|
if opts.help?
|
@@ -60,15 +65,38 @@ end
|
|
60
65
|
Encoding.default_external = Encoding::UTF_8
|
61
66
|
Encoding.default_internal = Encoding::UTF_8
|
62
67
|
|
63
|
-
license =
|
68
|
+
license = ''
|
69
|
+
if opts.license?
|
70
|
+
unless File.exist?(opts[:license])
|
71
|
+
puts "License file is absent: #{opts[:license]}"
|
72
|
+
exit -1
|
73
|
+
end
|
74
|
+
license = File.read(opts[:license])
|
75
|
+
end
|
76
|
+
|
77
|
+
files = Set.new
|
78
|
+
|
79
|
+
if opts[:include]
|
80
|
+
opts[:include].each do |glob|
|
81
|
+
files += Dir.glob(glob).map { |f| File.expand_path(f) }
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
files += opts.arguments.map { |f| File.expand_path(f) }
|
86
|
+
|
87
|
+
if opts[:exclude]
|
88
|
+
opts[:exclude].each do |glob|
|
89
|
+
files -= Dir.glob(glob).map { |f| File.expand_path(f) }
|
90
|
+
end
|
91
|
+
end
|
64
92
|
|
65
93
|
if opts.fix?
|
66
|
-
Xcop::CLI.new(
|
94
|
+
Xcop::CLI.new(files, license).fix do |f|
|
67
95
|
puts "#{f} fixed" unless opts.quiet?
|
68
96
|
end
|
69
97
|
else
|
70
98
|
begin
|
71
|
-
Xcop::CLI.new(
|
99
|
+
Xcop::CLI.new(files, license, nocolor: opts.nocolor?).run do |f|
|
72
100
|
puts "#{f} looks good" unless opts.quiet?
|
73
101
|
end
|
74
102
|
rescue StandardError => e
|
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright (c) 2017-
|
1
|
+
# Copyright (c) 2017-2022 Yegor Bugayenko
|
2
2
|
#
|
3
3
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
4
|
# of this software and associated documentation files (the 'Software'), to deal
|
@@ -22,7 +22,6 @@ require 'nokogiri'
|
|
22
22
|
require 'tmpdir'
|
23
23
|
require 'slop'
|
24
24
|
require 'English'
|
25
|
-
require_relative '../../lib/xcop'
|
26
25
|
|
27
26
|
Before do
|
28
27
|
@cwd = Dir.pwd
|
@@ -42,9 +41,7 @@ end
|
|
42
41
|
|
43
42
|
Given(/^I have a "([^"]*)" file with content:$/) do |file, text|
|
44
43
|
FileUtils.mkdir_p(File.dirname(file)) unless File.exist?(file)
|
45
|
-
File.
|
46
|
-
f.write(text.gsub(/\\xFF/, 0xFF.chr))
|
47
|
-
end
|
44
|
+
File.write(file, text.gsub(/\\xFF/, 0xFF.chr))
|
48
45
|
end
|
49
46
|
|
50
47
|
When(%r{^I run bin/xcop with "([^"]*)"$}) do |arg|
|
@@ -54,9 +51,7 @@ When(%r{^I run bin/xcop with "([^"]*)"$}) do |arg|
|
|
54
51
|
end
|
55
52
|
|
56
53
|
Then(/^Stdout contains "([^"]*)"$/) do |txt|
|
57
|
-
unless @stdout.include?(txt)
|
58
|
-
raise "STDOUT doesn't contain '#{txt}':\n#{@stdout}"
|
59
|
-
end
|
54
|
+
raise "STDOUT doesn't contain '#{txt}':\n#{@stdout}" unless @stdout.include?(txt)
|
60
55
|
end
|
61
56
|
|
62
57
|
Then(/^Stdout is empty$/) do
|
data/features/support/env.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright (c) 2017-
|
1
|
+
# Copyright (c) 2017-2022 Yegor Bugayenko
|
2
2
|
#
|
3
3
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
4
|
# of this software and associated documentation files (the 'Software'), to deal
|
@@ -19,4 +19,3 @@
|
|
19
19
|
# SOFTWARE.
|
20
20
|
|
21
21
|
require 'simplecov'
|
22
|
-
require_relative '../../lib/xcop'
|
data/lib/xcop/cli.rb
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
# Copyright (c) 2017-2022 Yegor Bugayenko
|
2
|
+
#
|
3
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
# of this software and associated documentation files (the 'Software'), to deal
|
5
|
+
# in the Software without restriction, including without limitation the rights
|
6
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
+
# copies of the Software, and to permit persons to whom the Software is
|
8
|
+
# furnished to do so, subject to the following conditions:
|
9
|
+
#
|
10
|
+
# The above copyright notice and this permission notice shall be included in all
|
11
|
+
# copies or substantial portions of the Software.
|
12
|
+
#
|
13
|
+
# THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
19
|
+
# SOFTWARE.
|
20
|
+
|
21
|
+
require 'nokogiri'
|
22
|
+
require 'differ'
|
23
|
+
require 'rainbow'
|
24
|
+
require_relative 'version'
|
25
|
+
require_relative 'document'
|
26
|
+
|
27
|
+
# Command line interface.
|
28
|
+
# Author:: Yegor Bugayenko (yegor256@gmail.com)
|
29
|
+
# Copyright:: Copyright (c) 2017-2022 Yegor Bugayenko
|
30
|
+
# License:: MIT
|
31
|
+
class Xcop::CLI
|
32
|
+
def initialize(files, license, nocolor: false)
|
33
|
+
@files = files
|
34
|
+
@license = license
|
35
|
+
@nocolor = nocolor
|
36
|
+
end
|
37
|
+
|
38
|
+
def run
|
39
|
+
@files.each do |f|
|
40
|
+
doc = Xcop::Document.new(f)
|
41
|
+
diff = doc.diff(nocolor: @nocolor)
|
42
|
+
unless diff.empty?
|
43
|
+
puts diff
|
44
|
+
raise "Invalid XML formatting in #{f}"
|
45
|
+
end
|
46
|
+
unless @license.empty?
|
47
|
+
ldiff = doc.ldiff(@license)
|
48
|
+
unless ldiff.empty?
|
49
|
+
puts ldiff
|
50
|
+
raise "Broken license in #{f}"
|
51
|
+
end
|
52
|
+
end
|
53
|
+
yield(f) if block_given?
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
# Fix them all.
|
58
|
+
def fix
|
59
|
+
@files.each do |f|
|
60
|
+
Xcop::Document.new(f).fix(@license)
|
61
|
+
yield(f) if block_given?
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
# Copyright (c) 2017-2022 Yegor Bugayenko
|
2
|
+
#
|
3
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
# of this software and associated documentation files (the 'Software'), to deal
|
5
|
+
# in the Software without restriction, including without limitation the rights
|
6
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
+
# copies of the Software, and to permit persons to whom the Software is
|
8
|
+
# furnished to do so, subject to the following conditions:
|
9
|
+
#
|
10
|
+
# The above copyright notice and this permission notice shall be included in all
|
11
|
+
# copies or substantial portions of the Software.
|
12
|
+
#
|
13
|
+
# THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
19
|
+
# SOFTWARE.
|
20
|
+
|
21
|
+
require 'nokogiri'
|
22
|
+
require 'differ'
|
23
|
+
require 'rainbow'
|
24
|
+
require_relative 'version'
|
25
|
+
|
26
|
+
# One document.
|
27
|
+
# Author:: Yegor Bugayenko (yegor256@gmail.com)
|
28
|
+
# Copyright:: Copyright (c) 2017-2022 Yegor Bugayenko
|
29
|
+
# License:: MIT
|
30
|
+
class Xcop::Document
|
31
|
+
# Ctor.
|
32
|
+
# +path+:: Path of it
|
33
|
+
def initialize(path)
|
34
|
+
@path = path
|
35
|
+
end
|
36
|
+
|
37
|
+
# Return the difference, if any (empty string if everything is clean).
|
38
|
+
def diff(nocolor: false)
|
39
|
+
xml = Nokogiri::XML(File.open(@path), &:noblanks)
|
40
|
+
ideal = xml.to_xml(indent: 2)
|
41
|
+
now = File.read(@path)
|
42
|
+
differ(ideal, now, nocolor: nocolor)
|
43
|
+
end
|
44
|
+
|
45
|
+
# Return the difference for the license.
|
46
|
+
def ldiff(license)
|
47
|
+
xml = Nokogiri::XML(File.open(@path), &:noblanks)
|
48
|
+
comment = xml.xpath('/comment()')[0]
|
49
|
+
now = comment.nil? ? '' : comment.text.to_s.strip
|
50
|
+
ideal = license.strip
|
51
|
+
differ(ideal, now)
|
52
|
+
end
|
53
|
+
|
54
|
+
# Fixes the document.
|
55
|
+
def fix(license = '')
|
56
|
+
xml = Nokogiri::XML(File.open(@path), &:noblanks)
|
57
|
+
unless license.empty?
|
58
|
+
xml.xpath('/comment()').remove
|
59
|
+
xml.children.before(
|
60
|
+
Nokogiri::XML::Comment.new(xml, "\n#{license.strip}\n")
|
61
|
+
)
|
62
|
+
end
|
63
|
+
ideal = xml.to_xml(indent: 2)
|
64
|
+
File.write(@path, ideal)
|
65
|
+
end
|
66
|
+
|
67
|
+
private
|
68
|
+
|
69
|
+
def differ(ideal, fact, nocolor: false)
|
70
|
+
return '' if ideal == fact
|
71
|
+
if nocolor
|
72
|
+
Differ.diff_by_line(ideal, fact).to_s
|
73
|
+
else
|
74
|
+
Differ.format = :color
|
75
|
+
Differ.diff_by_line(schars(ideal), schars(fact)).to_s
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def schars(text)
|
80
|
+
text.gsub(/\n/, "\\n\n")
|
81
|
+
end
|
82
|
+
end
|
data/lib/xcop/rake_task.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright (c) 2017-
|
1
|
+
# Copyright (c) 2017-2022 Yegor Bugayenko
|
2
2
|
#
|
3
3
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
4
|
# of this software and associated documentation files (the 'Software'), to deal
|
@@ -20,59 +20,51 @@
|
|
20
20
|
|
21
21
|
require 'rake'
|
22
22
|
require 'rake/tasklib'
|
23
|
-
require_relative '../xcop'
|
23
|
+
require_relative '../xcop/cli'
|
24
24
|
|
25
25
|
# Xcop rake task.
|
26
26
|
# Author:: Yegor Bugayenko (yegor256@gmail.com)
|
27
|
-
# Copyright:: Copyright (c) 2017-
|
27
|
+
# Copyright:: Copyright (c) 2017-2022 Yegor Bugayenko
|
28
28
|
# License:: MIT
|
29
|
-
|
30
|
-
|
31
|
-
class RakeTask < Rake::TaskLib
|
32
|
-
attr_accessor :name
|
33
|
-
attr_accessor :fail_on_error
|
34
|
-
attr_accessor :excludes
|
35
|
-
attr_accessor :includes
|
36
|
-
attr_accessor :license
|
37
|
-
attr_accessor :quiet
|
29
|
+
class Xcop::RakeTask < Rake::TaskLib
|
30
|
+
attr_accessor :name, :fail_on_error, :excludes, :includes, :license, :quiet
|
38
31
|
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
32
|
+
def initialize(*args, &task_block)
|
33
|
+
super()
|
34
|
+
@name = args.shift || :xcop
|
35
|
+
@includes = %w[xml xsd xhtml xsl html].map { |e| "**/*.#{e}" }
|
36
|
+
@excludes = []
|
37
|
+
@license = nil
|
38
|
+
@quiet = false
|
39
|
+
desc 'Run Xcop' unless ::Rake.application.last_description
|
40
|
+
task(name, *args) do |_, task_args|
|
41
|
+
RakeFileUtils.send(:verbose, true) do
|
42
|
+
yield(*[self, task_args].slice(0, task_block.arity)) if block_given?
|
43
|
+
run
|
51
44
|
end
|
52
45
|
end
|
46
|
+
end
|
53
47
|
|
54
|
-
|
48
|
+
private
|
55
49
|
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
print Rainbow('.').green unless @quiet
|
65
|
-
end
|
66
|
-
rescue StandardError => e
|
67
|
-
abort(e.message)
|
50
|
+
def run
|
51
|
+
puts 'Running xcop...' unless @quiet
|
52
|
+
bad = Dir.glob(@excludes)
|
53
|
+
good = Dir.glob(@includes).reject { |f| bad.include?(f) }
|
54
|
+
puts "Inspecting #{pluralize(good.length, 'file')}..." unless @quiet
|
55
|
+
begin
|
56
|
+
Xcop::CLI.new(good, @license.nil? ? '' : File.read(@license)).run do
|
57
|
+
print Rainbow('.').green unless @quiet
|
68
58
|
end
|
69
|
-
|
70
|
-
|
71
|
-
everything looks #{Rainbow('pretty').green}"
|
59
|
+
rescue StandardError => e
|
60
|
+
abort(e.message)
|
72
61
|
end
|
62
|
+
return if @quiet
|
63
|
+
puts "\n#{pluralize(good.length, 'file')} checked, \
|
64
|
+
everything looks #{Rainbow('pretty').green}"
|
65
|
+
end
|
73
66
|
|
74
|
-
|
75
|
-
|
76
|
-
end
|
67
|
+
def pluralize(num, text)
|
68
|
+
"#{num} #{num == 1 ? text : "#{text}s"}"
|
77
69
|
end
|
78
70
|
end
|
data/lib/xcop/version.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright (c) 2017-
|
1
|
+
# Copyright (c) 2017-2022 Yegor Bugayenko
|
2
2
|
#
|
3
3
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
4
|
# of this software and associated documentation files (the 'Software'), to deal
|
@@ -20,8 +20,8 @@
|
|
20
20
|
|
21
21
|
# Xcop main module.
|
22
22
|
# Author:: Yegor Bugayenko (yegor256@gmail.com)
|
23
|
-
# Copyright:: Copyright (c) 2017-
|
23
|
+
# Copyright:: Copyright (c) 2017-2022 Yegor Bugayenko
|
24
24
|
# License:: MIT
|
25
25
|
module Xcop
|
26
|
-
VERSION = '0.
|
26
|
+
VERSION = '0.7.0'.freeze
|
27
27
|
end
|
data/test/test__helper.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright (c) 2017-
|
1
|
+
# Copyright (c) 2017-2022 Yegor Bugayenko
|
2
2
|
#
|
3
3
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
4
|
# of this software and associated documentation files (the 'Software'), to deal
|
@@ -18,7 +18,7 @@
|
|
18
18
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
19
19
|
# SOFTWARE.
|
20
20
|
|
21
|
-
|
21
|
+
$stdout.sync = true
|
22
22
|
|
23
23
|
require 'simplecov'
|
24
24
|
SimpleCov.start
|
@@ -28,4 +28,3 @@ if ENV['CI'] == 'true'
|
|
28
28
|
end
|
29
29
|
|
30
30
|
require 'minitest/autorun'
|
31
|
-
require_relative '../lib/xcop'
|
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright (c) 2017-
|
1
|
+
# Copyright (c) 2017-2022 Yegor Bugayenko
|
2
2
|
#
|
3
3
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
4
|
# of this software and associated documentation files (the 'Software'), to deal
|
@@ -22,11 +22,11 @@ require 'minitest/autorun'
|
|
22
22
|
require 'nokogiri'
|
23
23
|
require 'tmpdir'
|
24
24
|
require 'slop'
|
25
|
-
require_relative '../lib/xcop'
|
25
|
+
require_relative '../lib/xcop/document'
|
26
26
|
|
27
|
-
#
|
27
|
+
# Test for Document class.
|
28
28
|
# Author:: Yegor Bugayenko (yegor256@gmail.com)
|
29
|
-
# Copyright:: Copyright (c) 2017-
|
29
|
+
# Copyright:: Copyright (c) 2017-2022 Yegor Bugayenko
|
30
30
|
# License:: MIT
|
31
31
|
class TestXcop < Minitest::Test
|
32
32
|
def test_basic
|
@@ -34,6 +34,7 @@ class TestXcop < Minitest::Test
|
|
34
34
|
f = File.join(dir, 'a.xml')
|
35
35
|
File.write(f, "<?xml version=\"1.0\"?>\n<hello>Dude!</hello>\n")
|
36
36
|
assert_equal(Xcop::Document.new(f).diff, '')
|
37
|
+
File.delete(f)
|
37
38
|
end
|
38
39
|
end
|
39
40
|
|
@@ -42,6 +43,7 @@ class TestXcop < Minitest::Test
|
|
42
43
|
f = File.join(dir, 'no-eol.xml')
|
43
44
|
File.write(f, "<?xml version=\"1.0\"?>\n<x/>")
|
44
45
|
assert(Xcop::Document.new(f).diff != '')
|
46
|
+
File.delete(f)
|
45
47
|
end
|
46
48
|
end
|
47
49
|
|
@@ -62,6 +64,7 @@ class TestXcop < Minitest::Test
|
|
62
64
|
].join("\n")
|
63
65
|
)
|
64
66
|
assert_equal(Xcop::Document.new(f).ldiff(license), '')
|
67
|
+
File.delete(f)
|
65
68
|
end
|
66
69
|
end
|
67
70
|
|
@@ -78,6 +81,7 @@ class TestXcop < Minitest::Test
|
|
78
81
|
].join("\n")
|
79
82
|
)
|
80
83
|
assert(Xcop::Document.new(f).ldiff(license) != '')
|
84
|
+
File.delete(f)
|
81
85
|
end
|
82
86
|
end
|
83
87
|
|
@@ -89,6 +93,7 @@ class TestXcop < Minitest::Test
|
|
89
93
|
Xcop::Document.new(f).fix(license)
|
90
94
|
assert_equal(Xcop::Document.new(f).diff, '')
|
91
95
|
assert_equal(Xcop::Document.new(f).ldiff(license), '')
|
96
|
+
File.delete(f)
|
92
97
|
end
|
93
98
|
end
|
94
99
|
|
@@ -100,6 +105,7 @@ class TestXcop < Minitest::Test
|
|
100
105
|
Xcop::Document.new(f).fix(license)
|
101
106
|
Xcop::Document.new(f).fix(license)
|
102
107
|
assert_equal(Nokogiri::XML(File.read(f)).xpath('/comment()').length, 1)
|
108
|
+
File.delete(f)
|
103
109
|
end
|
104
110
|
end
|
105
111
|
end
|
data/test/test_rake_task.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright (c) 2017-
|
1
|
+
# Copyright (c) 2017-2022 Yegor Bugayenko
|
2
2
|
#
|
3
3
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
4
|
# of this software and associated documentation files (the 'Software'), to deal
|
@@ -25,31 +25,35 @@ require_relative '../lib/xcop/rake_task'
|
|
25
25
|
|
26
26
|
# Xcop rake task.
|
27
27
|
# Author:: Yegor Bugayenko (yegor256@gmail.com)
|
28
|
-
# Copyright:: Copyright (c) 2017-
|
28
|
+
# Copyright:: Copyright (c) 2017-2022 Yegor Bugayenko
|
29
29
|
# License:: MIT
|
30
30
|
class TestRakeTask < Minitest::Test
|
31
31
|
def test_basic
|
32
32
|
Dir.mktmpdir 'test' do |dir|
|
33
33
|
Dir.chdir(dir)
|
34
|
-
File.
|
34
|
+
f = File.join(dir, 'a.xml')
|
35
|
+
File.write(f, "<?xml version=\"1.0\"?>\n<x/>\n")
|
35
36
|
Xcop::RakeTask.new(:xcop1) do |task|
|
36
37
|
task.quiet = true
|
37
38
|
# task.license = 'LICENSE.txt'
|
38
39
|
end
|
39
40
|
Rake::Task['xcop1'].invoke
|
41
|
+
File.delete(f)
|
40
42
|
end
|
41
43
|
end
|
42
44
|
|
43
45
|
def test_with_broken_xml
|
44
46
|
Dir.mktmpdir 'test' do |dir|
|
45
47
|
Dir.chdir(dir)
|
46
|
-
File.
|
48
|
+
f = File.join(dir, 'broken.xml')
|
49
|
+
File.write(f, "<z><a><b></b></a>\n\n</z>")
|
47
50
|
Xcop::RakeTask.new(:xcop2) do |task|
|
48
51
|
task.excludes = ['test/**/*']
|
49
52
|
end
|
50
53
|
assert_raises SystemExit do
|
51
54
|
Rake::Task['xcop2'].invoke
|
52
55
|
end
|
56
|
+
File.delete(f)
|
53
57
|
end
|
54
58
|
end
|
55
59
|
end
|
data/xcop.gemspec
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright (c) 2017-
|
1
|
+
# Copyright (c) 2017-2022 Yegor Bugayenko
|
2
2
|
#
|
3
3
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
4
|
# of this software and associated documentation files (the 'Software'), to deal
|
@@ -20,20 +20,19 @@
|
|
20
20
|
|
21
21
|
require 'English'
|
22
22
|
|
23
|
-
lib = File.expand_path('
|
23
|
+
lib = File.expand_path('lib', __dir__)
|
24
24
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
25
25
|
require_relative 'lib/xcop/version'
|
26
26
|
|
27
27
|
Gem::Specification.new do |s|
|
28
28
|
s.specification_version = 2 if s.respond_to? :specification_version=
|
29
|
-
if s.respond_to? :required_rubygems_version=
|
30
|
-
s.required_rubygems_version = Gem::Requirement.new('>= 0')
|
31
|
-
end
|
29
|
+
s.required_rubygems_version = Gem::Requirement.new('>= 0') if s.respond_to? :required_rubygems_version=
|
32
30
|
s.rubygems_version = '2.2'
|
33
31
|
s.required_ruby_version = '>= 2.2'
|
34
32
|
s.name = 'xcop'
|
35
33
|
s.version = Xcop::VERSION
|
36
34
|
s.license = 'MIT'
|
35
|
+
s.metadata = { 'rubygems_mfa_required' => 'true' }
|
37
36
|
s.summary = 'XML Formatting Static Validator'
|
38
37
|
s.description = 'Validates XML-like documents for proper formatting'
|
39
38
|
s.authors = ['Yegor Bugayenko']
|
@@ -41,18 +40,17 @@ Gem::Specification.new do |s|
|
|
41
40
|
s.homepage = 'http://github.com/yegor256/xcop'
|
42
41
|
s.files = `git ls-files`.split($RS)
|
43
42
|
s.executables = s.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
44
|
-
s.test_files = s.files.grep(%r{^(test|spec|features)/})
|
45
43
|
s.rdoc_options = ['--charset=UTF-8']
|
46
44
|
s.extra_rdoc_files = ['README.md', 'LICENSE.txt']
|
47
45
|
s.add_runtime_dependency 'differ', '~>0.1.2'
|
48
46
|
s.add_runtime_dependency 'nokogiri', '~>1.10'
|
49
47
|
s.add_runtime_dependency 'rainbow', '~>3.0'
|
50
48
|
s.add_runtime_dependency 'slop', '~>4.4'
|
51
|
-
s.add_development_dependency 'codecov', '0.
|
52
|
-
s.add_development_dependency 'cucumber', '
|
53
|
-
s.add_development_dependency 'minitest', '5.
|
54
|
-
s.add_development_dependency 'rake', '13.0.
|
55
|
-
s.add_development_dependency 'rdoc', '6.
|
56
|
-
s.add_development_dependency 'rubocop', '
|
57
|
-
s.add_development_dependency 'rubocop-rspec', '
|
49
|
+
s.add_development_dependency 'codecov', '0.6.0'
|
50
|
+
s.add_development_dependency 'cucumber', '8.0.0'
|
51
|
+
s.add_development_dependency 'minitest', '5.15.0'
|
52
|
+
s.add_development_dependency 'rake', '13.0.6'
|
53
|
+
s.add_development_dependency 'rdoc', '6.4.0'
|
54
|
+
s.add_development_dependency 'rubocop', '1.30.1'
|
55
|
+
s.add_development_dependency 'rubocop-rspec', '2.11.1'
|
58
56
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: xcop
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.7.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Yegor Bugayenko
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2022-06-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: differ
|
@@ -72,98 +72,98 @@ dependencies:
|
|
72
72
|
requirements:
|
73
73
|
- - '='
|
74
74
|
- !ruby/object:Gem::Version
|
75
|
-
version: 0.
|
75
|
+
version: 0.6.0
|
76
76
|
type: :development
|
77
77
|
prerelease: false
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
79
79
|
requirements:
|
80
80
|
- - '='
|
81
81
|
- !ruby/object:Gem::Version
|
82
|
-
version: 0.
|
82
|
+
version: 0.6.0
|
83
83
|
- !ruby/object:Gem::Dependency
|
84
84
|
name: cucumber
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|
86
86
|
requirements:
|
87
87
|
- - '='
|
88
88
|
- !ruby/object:Gem::Version
|
89
|
-
version:
|
89
|
+
version: 8.0.0
|
90
90
|
type: :development
|
91
91
|
prerelease: false
|
92
92
|
version_requirements: !ruby/object:Gem::Requirement
|
93
93
|
requirements:
|
94
94
|
- - '='
|
95
95
|
- !ruby/object:Gem::Version
|
96
|
-
version:
|
96
|
+
version: 8.0.0
|
97
97
|
- !ruby/object:Gem::Dependency
|
98
98
|
name: minitest
|
99
99
|
requirement: !ruby/object:Gem::Requirement
|
100
100
|
requirements:
|
101
101
|
- - '='
|
102
102
|
- !ruby/object:Gem::Version
|
103
|
-
version: 5.
|
103
|
+
version: 5.15.0
|
104
104
|
type: :development
|
105
105
|
prerelease: false
|
106
106
|
version_requirements: !ruby/object:Gem::Requirement
|
107
107
|
requirements:
|
108
108
|
- - '='
|
109
109
|
- !ruby/object:Gem::Version
|
110
|
-
version: 5.
|
110
|
+
version: 5.15.0
|
111
111
|
- !ruby/object:Gem::Dependency
|
112
112
|
name: rake
|
113
113
|
requirement: !ruby/object:Gem::Requirement
|
114
114
|
requirements:
|
115
115
|
- - '='
|
116
116
|
- !ruby/object:Gem::Version
|
117
|
-
version: 13.0.
|
117
|
+
version: 13.0.6
|
118
118
|
type: :development
|
119
119
|
prerelease: false
|
120
120
|
version_requirements: !ruby/object:Gem::Requirement
|
121
121
|
requirements:
|
122
122
|
- - '='
|
123
123
|
- !ruby/object:Gem::Version
|
124
|
-
version: 13.0.
|
124
|
+
version: 13.0.6
|
125
125
|
- !ruby/object:Gem::Dependency
|
126
126
|
name: rdoc
|
127
127
|
requirement: !ruby/object:Gem::Requirement
|
128
128
|
requirements:
|
129
129
|
- - '='
|
130
130
|
- !ruby/object:Gem::Version
|
131
|
-
version: 6.
|
131
|
+
version: 6.4.0
|
132
132
|
type: :development
|
133
133
|
prerelease: false
|
134
134
|
version_requirements: !ruby/object:Gem::Requirement
|
135
135
|
requirements:
|
136
136
|
- - '='
|
137
137
|
- !ruby/object:Gem::Version
|
138
|
-
version: 6.
|
138
|
+
version: 6.4.0
|
139
139
|
- !ruby/object:Gem::Dependency
|
140
140
|
name: rubocop
|
141
141
|
requirement: !ruby/object:Gem::Requirement
|
142
142
|
requirements:
|
143
143
|
- - '='
|
144
144
|
- !ruby/object:Gem::Version
|
145
|
-
version:
|
145
|
+
version: 1.30.1
|
146
146
|
type: :development
|
147
147
|
prerelease: false
|
148
148
|
version_requirements: !ruby/object:Gem::Requirement
|
149
149
|
requirements:
|
150
150
|
- - '='
|
151
151
|
- !ruby/object:Gem::Version
|
152
|
-
version:
|
152
|
+
version: 1.30.1
|
153
153
|
- !ruby/object:Gem::Dependency
|
154
154
|
name: rubocop-rspec
|
155
155
|
requirement: !ruby/object:Gem::Requirement
|
156
156
|
requirements:
|
157
157
|
- - '='
|
158
158
|
- !ruby/object:Gem::Version
|
159
|
-
version:
|
159
|
+
version: 2.11.1
|
160
160
|
type: :development
|
161
161
|
prerelease: false
|
162
162
|
version_requirements: !ruby/object:Gem::Requirement
|
163
163
|
requirements:
|
164
164
|
- - '='
|
165
165
|
- !ruby/object:Gem::Version
|
166
|
-
version:
|
166
|
+
version: 2.11.1
|
167
167
|
description: Validates XML-like documents for proper formatting
|
168
168
|
email: yegor256@gmail.com
|
169
169
|
executables:
|
@@ -177,17 +177,16 @@ files:
|
|
177
177
|
- ".gitattributes"
|
178
178
|
- ".github/ISSUE_TEMPLATE.md"
|
179
179
|
- ".github/PULL_REQUEST_TEMPLATE.md"
|
180
|
+
- ".github/workflows/rake.yml"
|
180
181
|
- ".gitignore"
|
181
182
|
- ".pdd"
|
182
183
|
- ".rubocop.yml"
|
183
184
|
- ".rultor.yml"
|
184
185
|
- ".simplecov"
|
185
|
-
- ".travis.yml"
|
186
186
|
- Gemfile
|
187
187
|
- LICENSE.txt
|
188
188
|
- README.md
|
189
189
|
- Rakefile
|
190
|
-
- appveyor.yml
|
191
190
|
- bin/xcop
|
192
191
|
- cucumber.yml
|
193
192
|
- features/cli.feature
|
@@ -195,18 +194,20 @@ files:
|
|
195
194
|
- features/rake.feature
|
196
195
|
- features/step_definitions/steps.rb
|
197
196
|
- features/support/env.rb
|
198
|
-
- lib/xcop.rb
|
197
|
+
- lib/xcop/cli.rb
|
198
|
+
- lib/xcop/document.rb
|
199
199
|
- lib/xcop/rake_task.rb
|
200
200
|
- lib/xcop/version.rb
|
201
201
|
- logo.svg
|
202
202
|
- test/test__helper.rb
|
203
|
+
- test/test_document.rb
|
203
204
|
- test/test_rake_task.rb
|
204
|
-
- test/test_xcop.rb
|
205
205
|
- xcop.gemspec
|
206
206
|
homepage: http://github.com/yegor256/xcop
|
207
207
|
licenses:
|
208
208
|
- MIT
|
209
|
-
metadata:
|
209
|
+
metadata:
|
210
|
+
rubygems_mfa_required: 'true'
|
210
211
|
post_install_message:
|
211
212
|
rdoc_options:
|
212
213
|
- "--charset=UTF-8"
|
@@ -227,12 +228,4 @@ rubygems_version: 3.1.2
|
|
227
228
|
signing_key:
|
228
229
|
specification_version: 2
|
229
230
|
summary: XML Formatting Static Validator
|
230
|
-
test_files:
|
231
|
-
- features/cli.feature
|
232
|
-
- features/gem_package.feature
|
233
|
-
- features/rake.feature
|
234
|
-
- features/step_definitions/steps.rb
|
235
|
-
- features/support/env.rb
|
236
|
-
- test/test__helper.rb
|
237
|
-
- test/test_rake_task.rb
|
238
|
-
- test/test_xcop.rb
|
231
|
+
test_files: []
|
data/.travis.yml
DELETED
data/appveyor.yml
DELETED
@@ -1,21 +0,0 @@
|
|
1
|
-
version: '{build}'
|
2
|
-
skip_tags: true
|
3
|
-
clone_depth: 10
|
4
|
-
branches:
|
5
|
-
only:
|
6
|
-
- master
|
7
|
-
except:
|
8
|
-
- gh-pages
|
9
|
-
os: Windows Server 2012
|
10
|
-
install:
|
11
|
-
- cmd: SET PATH=C:\Ruby23-x64\bin;%PATH%
|
12
|
-
- cmd: ruby --version
|
13
|
-
- cmd: git --version
|
14
|
-
build_script:
|
15
|
-
- bundle update
|
16
|
-
- bundle install
|
17
|
-
test_script:
|
18
|
-
- rake
|
19
|
-
cache:
|
20
|
-
- C:\Ruby200\bin -> xcop.gemspec
|
21
|
-
- C:\Ruby200\lib\ruby\gems\2.0.0 -> xcop.gemspec
|
data/lib/xcop.rb
DELETED
@@ -1,121 +0,0 @@
|
|
1
|
-
# Copyright (c) 2017-2021 Yegor Bugayenko
|
2
|
-
#
|
3
|
-
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
-
# of this software and associated documentation files (the 'Software'), to deal
|
5
|
-
# in the Software without restriction, including without limitation the rights
|
6
|
-
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
-
# copies of the Software, and to permit persons to whom the Software is
|
8
|
-
# furnished to do so, subject to the following conditions:
|
9
|
-
#
|
10
|
-
# The above copyright notice and this permission notice shall be included in all
|
11
|
-
# copies or substantial portions of the Software.
|
12
|
-
#
|
13
|
-
# THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
-
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
-
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFINGEMENT. IN NO EVENT SHALL THE
|
16
|
-
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
-
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
-
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
19
|
-
# SOFTWARE.
|
20
|
-
|
21
|
-
require 'nokogiri'
|
22
|
-
require 'differ'
|
23
|
-
require 'rainbow'
|
24
|
-
require_relative 'xcop/version'
|
25
|
-
|
26
|
-
# Xcop main module.
|
27
|
-
# Author:: Yegor Bugayenko (yegor256@gmail.com)
|
28
|
-
# Copyright:: Copyright (c) 2017-2021 Yegor Bugayenko
|
29
|
-
# License:: MIT
|
30
|
-
module Xcop
|
31
|
-
# Command line interface.
|
32
|
-
class CLI
|
33
|
-
def initialize(files, license, nocolor = false)
|
34
|
-
@files = files
|
35
|
-
@license = license
|
36
|
-
@nocolor = nocolor
|
37
|
-
end
|
38
|
-
|
39
|
-
def run
|
40
|
-
@files.each do |f|
|
41
|
-
doc = Document.new(f)
|
42
|
-
diff = doc.diff(@nocolor)
|
43
|
-
unless diff.empty?
|
44
|
-
puts diff
|
45
|
-
raise "Invalid XML formatting in #{f}"
|
46
|
-
end
|
47
|
-
unless @license.empty?
|
48
|
-
ldiff = doc.ldiff(@license)
|
49
|
-
unless ldiff.empty?
|
50
|
-
puts ldiff
|
51
|
-
raise "Broken license in #{f}"
|
52
|
-
end
|
53
|
-
end
|
54
|
-
yield(f) if block_given?
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
|
-
# Fix them all.
|
59
|
-
def fix
|
60
|
-
@files.each do |f|
|
61
|
-
Document.new(f).fix(@license)
|
62
|
-
yield(f) if block_given?
|
63
|
-
end
|
64
|
-
end
|
65
|
-
end
|
66
|
-
|
67
|
-
# One document.
|
68
|
-
class Document
|
69
|
-
# Ctor.
|
70
|
-
# +path+:: Path of it
|
71
|
-
def initialize(path)
|
72
|
-
@path = path
|
73
|
-
end
|
74
|
-
|
75
|
-
# Return the difference, if any (empty string if everything is clean).
|
76
|
-
def diff(nocolor = false)
|
77
|
-
xml = Nokogiri::XML(File.open(@path), &:noblanks)
|
78
|
-
ideal = xml.to_xml(indent: 2)
|
79
|
-
now = File.read(@path)
|
80
|
-
differ(ideal, now, nocolor)
|
81
|
-
end
|
82
|
-
|
83
|
-
# Return the difference for the license.
|
84
|
-
def ldiff(license)
|
85
|
-
xml = Nokogiri::XML(File.open(@path), &:noblanks)
|
86
|
-
comment = xml.xpath('/comment()')[0]
|
87
|
-
now = comment.nil? ? '' : comment.text.to_s.strip
|
88
|
-
ideal = license.strip
|
89
|
-
differ(ideal, now)
|
90
|
-
end
|
91
|
-
|
92
|
-
# Fixes the document.
|
93
|
-
def fix(license = '')
|
94
|
-
xml = Nokogiri::XML(File.open(@path), &:noblanks)
|
95
|
-
unless license.empty?
|
96
|
-
xml.xpath('/comment()').remove
|
97
|
-
xml.children.before(
|
98
|
-
Nokogiri::XML::Comment.new(xml, "\n#{license.strip}\n")
|
99
|
-
)
|
100
|
-
end
|
101
|
-
ideal = xml.to_xml(indent: 2)
|
102
|
-
File.write(@path, ideal)
|
103
|
-
end
|
104
|
-
|
105
|
-
private
|
106
|
-
|
107
|
-
def differ(ideal, fact, nocolor = false)
|
108
|
-
return '' if ideal == fact
|
109
|
-
if nocolor
|
110
|
-
Differ.diff_by_line(ideal, fact).to_s
|
111
|
-
else
|
112
|
-
Differ.format = :color
|
113
|
-
Differ.diff_by_line(schars(ideal), schars(fact)).to_s
|
114
|
-
end
|
115
|
-
end
|
116
|
-
|
117
|
-
def schars(text)
|
118
|
-
text.gsub(/\n/, "\\n\n")
|
119
|
-
end
|
120
|
-
end
|
121
|
-
end
|