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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1e36ceb8094cf5d0a19aea136e067aefead3f8d2d5d0be89ee04621bf377ea9f
4
- data.tar.gz: 0ada0467d87ee9bd8eee76b455093d8eaf651d5297db98ba0c06a8f9cbdacd35
3
+ metadata.gz: 94e8fcd3843e72e2e95cc964a20acd22527734574d2da826e58b0b51fd50ead1
4
+ data.tar.gz: f454cfb06eecd4700b92c86c815bc4207d7554c455db2fba2d17a46f6c5cbc49
5
5
  SHA512:
6
- metadata.gz: 95e7400cf83b268b35464cb701e8eda47e3f1db96d6d7dbb881a3d1cde7776dd6d5888334cd7c5f26f5727868e56638c06c6f9fe8da39a8a3f59156e33d9b338
7
- data.tar.gz: b5535146d433e5bb9d37967f523e8851b6dfebf1486e6b4d0cdf41a4db72e0caefc821587bd0d9c791f0c46f4b1c76af1481a8470d411398d177ba51e0b26ca2
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
- Style/MultilineMethodCallIndentation:
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
- export GEM_HOME=~/.ruby
5
- export GEM_PATH=$GEM_HOME:$GEM_PATH
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/1\.0\.snapshot/${tag}/g" lib/xcop/version.rb
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-2021 Yegor Bugayenko
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? then
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 "/test/"
27
- add_filter "/features/"
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 "/test/"
35
- add_filter "/features/"
34
+ add_filter '/test/'
35
+ add_filter '/features/'
36
36
  minimum_coverage 80
37
37
  end
38
38
  end
data/Gemfile CHANGED
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2017-2021 Yegor Bugayenko
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
data/LICENSE.txt CHANGED
@@ -1,6 +1,6 @@
1
1
  (The MIT License)
2
2
 
3
- Copyright (c) 2017-2021 Yegor Bugayenko
3
+ Copyright (c) 2017-2022 Yegor Bugayenko
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the 'Software'), to deal
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
  [![EO principles respected here](https://www.elegantobjects.org/badge.svg)](https://www.elegantobjects.org)
4
4
  [![Managed by Zerocracy](https://www.0crat.com/badge/C3RFVLU72.svg)](https://www.0crat.com/p/C3RFVLU72)
5
5
  [![DevOps By Rultor.com](http://www.rultor.com/b/yegor256/xcop)](http://www.rultor.com/p/yegor256/xcop)
6
6
  [![We recommend RubyMine](https://www.elegantobjects.org/rubymine.svg)](https://www.jetbrains.com/ruby/)
7
7
 
8
- [![Build Status](https://travis-ci.org/yegor256/xcop.svg)](https://travis-ci.org/yegor256/xcop)
9
- [![Build status](https://ci.appveyor.com/api/projects/status/orvfo2qgmd1d7a2i?svg=true)](https://ci.appveyor.com/project/yegor256/xcop)
8
+ [![rake](https://github.com/yegor256/xcop/actions/workflows/rake.yml/badge.svg)](https://github.com/yegor256/xcop/actions/workflows/rake.yml)
10
9
  [![PDD status](http://www.0pdd.com/svg?name=yegor256/xcop)](http://www.0pdd.com/p?name=yegor256/xcop)
11
10
  [![Gem Version](https://badge.fury.io/rb/xcop.svg)](http://badge.fury.io/rb/xcop)
12
11
  [![License](https://img.shields.io/badge/license-MIT-green.svg)](https://github.com/yegor256/xcop/blob/master/LICENSE.txt)
13
12
 
14
13
  [![Maintainability](https://api.codeclimate.com/v1/badges/396ec0584e0a84adc723/maintainability)](https://codeclimate.com/github/yegor256/xcop/maintainability)
15
14
  [![Test Coverage](https://img.shields.io/codecov/c/github/yegor256/xcop.svg)](https://codecov.io/github/yegor256/xcop?branch=master)
15
+ ![Lines of code](https://img.shields.io/tokei/lines/github/yegor256/xcop)
16
16
  [![Hits-of-Code](https://hitsofcode.com/github/yegor256/xcop)](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
- returns with an error. You can use it two ways: 1) to fail your build
21
- if any X-like files (XML, XSD, XSL, XHTML) are not formatted correctly,
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 of mine first:
24
+ Read this blog post first:
25
25
  [_XCOP—XML Style Checker_](https://www.yegor256.com/2017/08/29/xcop.html).
26
26
 
27
- Install it first (read below if you can't install it):
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-2021 Yegor Bugayenko
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-2021 Yegor Bugayenko
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
- require_relative '../lib/xcop'
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
- file_cfg = []
34
- if File.exist?('.xcop')
35
- file_cfg += File.open('.xcop').read.gsub(/\s+/, " ").strip.split(/\s/)
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
- merged = ARGV + file_cfg
41
+ args = config('~/.xcop') + config('.xcop') + ARGV
39
42
 
40
- opts = Slop.parse(merged, strict: true, help: true) do |o|
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 = opts.license? ? File.read(opts[: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(opts.arguments, license).fix do |f|
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(opts.arguments, license, opts.nocolor?).run do |f|
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-2021 Yegor Bugayenko
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.open(file, 'w') do |f|
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
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2017-2021 Yegor Bugayenko
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
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2017-2021 Yegor Bugayenko
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-2021 Yegor Bugayenko
27
+ # Copyright:: Copyright (c) 2017-2022 Yegor Bugayenko
28
28
  # License:: MIT
29
- module Xcop
30
- # Rake task.
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
- def initialize(*args, &task_block)
40
- @name = args.shift || :xcop
41
- @includes = %w[xml xsd xhtml xsl html].map { |e| "**/*.#{e}" }
42
- @excludes = []
43
- @license = nil
44
- @quiet = false
45
- desc 'Run Xcop' unless ::Rake.application.last_description
46
- task(name, *args) do |_, task_args|
47
- RakeFileUtils.send(:verbose, true) do
48
- yield(*[self, task_args].slice(0, task_block.arity)) if block_given?
49
- run
50
- end
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
- private
48
+ private
55
49
 
56
- def run
57
- require 'xcop'
58
- puts 'Running xcop...' unless @quiet
59
- bad = Dir.glob(@excludes)
60
- good = Dir.glob(@includes).reject { |f| bad.include?(f) }
61
- puts "Inspecting #{pluralize(good.length, 'file')}..." unless @quiet
62
- begin
63
- Xcop::CLI.new(good, @license.nil? ? '' : File.read(@license)).run do
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
- return if @quiet
70
- puts "\n#{pluralize(good.length, 'file')} checked, \
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
- def pluralize(num, text)
75
- "#{num} #{num == 1 ? text : text + 's'}"
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-2021 Yegor Bugayenko
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-2021 Yegor Bugayenko
23
+ # Copyright:: Copyright (c) 2017-2022 Yegor Bugayenko
24
24
  # License:: MIT
25
25
  module Xcop
26
- VERSION = '0.6.3'.freeze
26
+ VERSION = '0.7.0'.freeze
27
27
  end
data/test/test__helper.rb CHANGED
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2017-2021 Yegor Bugayenko
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
- STDOUT.sync = true
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-2021 Yegor Bugayenko
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
- # Xcop main module test.
27
+ # Test for Document class.
28
28
  # Author:: Yegor Bugayenko (yegor256@gmail.com)
29
- # Copyright:: Copyright (c) 2017-2021 Yegor Bugayenko
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
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2017-2021 Yegor Bugayenko
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-2021 Yegor Bugayenko
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.write('a.xml', "<?xml version=\"1.0\"?>\n<x/>\n")
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.write('broken.xml', "<z><a><b></b></a>\n\n</z>")
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-2021 Yegor Bugayenko
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('../lib', __FILE__)
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.2.12'
52
- s.add_development_dependency 'cucumber', '5.2.0'
53
- s.add_development_dependency 'minitest', '5.14.2'
54
- s.add_development_dependency 'rake', '13.0.1'
55
- s.add_development_dependency 'rdoc', '6.2.1'
56
- s.add_development_dependency 'rubocop', '0.52.0'
57
- s.add_development_dependency 'rubocop-rspec', '1.5.1'
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.6.3
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: 2021-09-12 00:00:00.000000000 Z
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.2.12
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.2.12
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: 5.2.0
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: 5.2.0
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.14.2
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.14.2
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.1
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.1
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.2.1
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.2.1
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: 0.52.0
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: 0.52.0
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: 1.5.1
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: 1.5.1
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
@@ -1,13 +0,0 @@
1
- language: ruby
2
- rvm:
3
- - 2.2.2
4
- cache: bundler
5
- branches:
6
- only:
7
- - master
8
- install:
9
- - travis_retry bundle update
10
- script:
11
- - bundle exec rake
12
- after_success:
13
- - "bash <(curl -s https://codecov.io/bash)"
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