repo-compare 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 773b51d17d77a75045e4ef688366a80c4c00dc5de265792789c50c1797cf446d
4
+ data.tar.gz: 54fdb63bf82c42bf11aefa6cb3bd7565d8184a6744bd59efdbb8fed718117a55
5
+ SHA512:
6
+ metadata.gz: be45085c8b9118870b9493633ecbed8d536b17296225ed8c258b40e33cc0161c5aab23a22d63284f749497187f4852e37a27634e82ef4e1a2ff97954dc0e80cb
7
+ data.tar.gz: 3a1c720c912fdf315bc8492d9ac329004ca88cc984967b1ddb04f72e046820dc52b9dc80347036750601ae32701b08608b045708db4f7928daeb4f7845332763
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2021 Mattia Roccoberton
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,57 @@
1
+ # Repo Compare
2
+
3
+ Track changes of another repository.
4
+
5
+ Features:
6
+ - check multiple paths of a repo;
7
+ - create a summary of the changes using git compare (`-s` option);
8
+ - create a detailed list of diffs;
9
+ - ignore some changes to a specific file, saving hashes locally (`-u` option).
10
+
11
+ It can be useful keep track of the changes of a master repo from a forked project, eventually preparing a check in the CI.
12
+
13
+ **IMPORTANT**: the tool will add the other repository as remote source.
14
+
15
+ ## Installation
16
+
17
+ - Add to your Gemfile: `gem 'repo-compare', require: false` (and execute `bundle`)
18
+ - Create a config file in the root of your project (`.repo-compare.yml`):
19
+
20
+ ```yml
21
+ ---
22
+ source_name: REPO_NAME
23
+ source_branch: master
24
+ source_base_path: OPTIONAL_INTERNAL_PATH
25
+ source_repo: https://github.com/ACCOUNT_NAME/REPO_NAME.git
26
+ paths:
27
+ - PATH1
28
+ - PATH2
29
+ - PATH3
30
+ - ...
31
+ ```
32
+
33
+ - Execute the binary: `bundle exec repo-compare`
34
+
35
+ Alternative option, install it at system level: `gem install repo-compare`
36
+
37
+ ## Usage
38
+
39
+ The tool accepts some command line option:
40
+
41
+ - `-h` or `--help` : show this help
42
+ - `-s` or `--summary` : generate an XML summary of the files changed (useful for CI)
43
+ - `-u` or `--update` : update the config file setting the current hashes to ignore
44
+
45
+ ## Do you like it? Star it!
46
+
47
+ If you use this component just star it. A developer is more motivated to improve a project when there is some interest.
48
+
49
+ Or consider offering me a coffee, it's a small thing but it is greatly appreciated: [about me](https://www.blocknot.es/about-me).
50
+
51
+ ## Contributors
52
+
53
+ - [Mattia Roccoberton](https://blocknot.es/): author
54
+
55
+ ## License
56
+
57
+ The gem is available as open source under the terms of the [MIT License](MIT-LICENSE).
data/Rakefile ADDED
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/gem_tasks'
4
+
5
+ begin
6
+ require 'rspec/core/rake_task'
7
+
8
+ RSpec::Core::RakeTask.new(:spec) do |t|
9
+ # t.ruby_opts = %w[-w]
10
+ t.rspec_opts = ['--color', '--format documentation']
11
+ end
12
+
13
+ task default: :spec
14
+ rescue LoadError
15
+ puts '! LoadError: no RSpec available'
16
+ end
data/bin/repo-compare ADDED
@@ -0,0 +1,55 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require 'repo-compare/config'
5
+ require 'repo-compare/git_remote_update'
6
+ require 'repo-compare/git_diff'
7
+ require 'repo-compare/git_diff_raw'
8
+ require 'repo-compare/summary'
9
+
10
+ # Check the arguments
11
+ action = nil
12
+ ARGV.each do |arg|
13
+ case arg
14
+ when '-h', '--help'
15
+ puts <<~HELP
16
+ Repo Compare: a tool to detect changes between 2 repositories
17
+
18
+ Options:
19
+ -h or --help : show this help
20
+ -s or --summary : generate an XML summary of the files changed (useful for CI)
21
+ -u or --update : update the config file setting the current hashes to ignore
22
+ HELP
23
+ exit 0
24
+ when '-s', '--summary'
25
+ action = :summary
26
+ when '-u', '--update'
27
+ action = :update
28
+ end
29
+ end
30
+
31
+ # Load the config options
32
+ config = RepoCompare::Config.new
33
+ config_hash = config.to_h
34
+
35
+ # Update the remote source
36
+ RepoCompare::GitRemoteUpdate.new(config_hash).call
37
+
38
+ # Compare paths
39
+ results = config_hash['paths'].map do |path|
40
+ RepoCompare::GitDiffRaw.new(config_hash, path).call.merge(src: path)
41
+ end
42
+
43
+ if action == :summary
44
+ # Prepare a summary
45
+ puts RepoCompare::Summary.new(results).to_xml
46
+ else
47
+ # Prepare a detailed diff
48
+ results.each do |res|
49
+ diff = RepoCompare::GitDiff.new(config_hash, res).call
50
+ puts diff unless diff.empty?
51
+ end
52
+ end
53
+
54
+ # Update the config
55
+ config.update(results) if action == :update
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'yaml'
4
+
5
+ module RepoCompare
6
+ # Load configuration
7
+ class Config
8
+ CONFIG_PATH = '.repo-compare.yml'
9
+
10
+ def initialize
11
+ @config = File.exist?(CONFIG_PATH) ? YAML.load_file(CONFIG_PATH) : {}
12
+ @config['paths'] ||= []
13
+ @config['ignore'] ||= {}
14
+ @config['source_branch'] ||= 'master'
15
+ end
16
+
17
+ def to_h
18
+ @config.to_h
19
+ end
20
+
21
+ def update(results)
22
+ results.each do |result|
23
+ @config['ignore'][result[:src]] ||= {}
24
+ update_conf_path(@config['ignore'][result[:src]], result[:results])
25
+ end
26
+ File.open(CONFIG_PATH, 'w') { |f| f.puts(@config.to_yaml) }
27
+ end
28
+
29
+ private
30
+
31
+ def update_conf_path(conf, results)
32
+ results.each do |path, hash|
33
+ # require 'pry'; binding.pry
34
+ if conf[path]
35
+ # TODO: update...
36
+ else
37
+ conf[path] = hash
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RepoCompare
4
+ # Compare 2 repos
5
+ class GitDiff
6
+ def initialize(config, result)
7
+ @config = config
8
+ @result = result
9
+ end
10
+
11
+ def call
12
+ @result[:results].map do |paths, _hash|
13
+ diff(paths)
14
+ end.join("\n")
15
+ end
16
+
17
+ private
18
+
19
+ def diff(paths)
20
+ src, dst = paths.split("\t")
21
+ dst ||= src
22
+ `git diff 'remotes/#{@config['source_name']}/#{@config['source_branch']}' -- '#{src}' '#{dst}'`
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RepoCompare
4
+ # Compare 2 repos
5
+ class GitDiffRaw
6
+ DIFF_OPTIONS = '--cc --raw'
7
+ EXP = /:\w+ \w+ (?<src>\w+) (?<dst>\w+) (?<status>\w+)\t(?<path>.+)/.freeze
8
+
9
+ def initialize(config, path)
10
+ @config = config
11
+ @context = { output: [] }
12
+ @path = path
13
+ end
14
+
15
+ def call
16
+ compare_repos
17
+ filter_changes
18
+ extract_results
19
+ @context.merge!(success?: true)
20
+ end
21
+
22
+ private
23
+
24
+ def compare_repos
25
+ cmd = "git diff #{DIFF_OPTIONS} 'remotes/#{@config['source_name']}/#{@config['source_branch']}' -- "
26
+ cmd += "'#{@config['source_base_path']}/#{@path}' '#{@path}'"
27
+ @context[:output] = `#{cmd}`.scan(EXP)
28
+ @context
29
+ end
30
+
31
+ def extract_results
32
+ @context[:output].sort_by! { |item| item[3] }
33
+ @context[:results] = {}
34
+ @context[:output].each_with_object(@context[:results]) do |item, ret|
35
+ ret[item[3]] = item[0]
36
+ end
37
+ @context
38
+ end
39
+
40
+ def filter_changes
41
+ ignore = @config['ignore'][@path] || []
42
+ @context[:output].reject! { |line| line[0] == line[1] || ignore_changes?(ignore, line) }
43
+ @context
44
+ end
45
+
46
+ def ignore_changes?(ignore, line)
47
+ path = line[3]
48
+ ignore[path] == '-' || ignore[path] == line[0]
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RepoCompare
4
+ # Update the remote source
5
+ class GitRemoteUpdate
6
+ def initialize(config)
7
+ @config = config
8
+ end
9
+
10
+ def call
11
+ if `git remote`.split("\n").none? @config['source_name']
12
+ `git remote add -f #{@config['source_name']} #{@config['source_repo']}`
13
+ puts('error with git remote add') & exit if $?.exitstatus != 0
14
+ end
15
+
16
+ `git remote update > /dev/null 2>&1`
17
+ puts('error with git remote update') & exit if $?.exitstatus != 0
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'date'
4
+
5
+ module RepoCompare
6
+ # Create a diff summary
7
+ class Summary
8
+ def initialize(results)
9
+ @count = 0
10
+ @results = results || []
11
+ end
12
+
13
+ def to_xml
14
+ <<~SUMMARY
15
+ <?xml version="1.0" encoding="UTF-8"?>
16
+ <testsuite name="solidus_compare" tests="#{@count}" skipped="0" failures="#{@count}" errors="#{@count}" time="1" timestamp="#{DateTime.now.iso8601}">
17
+ #{testcases}</testsuite>
18
+ SUMMARY
19
+ end
20
+
21
+ private
22
+
23
+ def testcases
24
+ @results.map do |result|
25
+ result[:results].map do |paths, hash|
26
+ @count += 1
27
+ # result[:src]
28
+ name = paths.gsub(/\t/, ' - ')
29
+ file = paths.split("\t")[-1]
30
+ "<testcase name=\"#{name}\" file=\"#{file}\" time=\"0\"><failure>hash: #{hash}\nfile: #{paths}</failure></testcase>"
31
+ end.join("\n")
32
+ end.join("\n")
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RepoCompare
4
+ VERSION = '0.1.0'
5
+ end
metadata ADDED
@@ -0,0 +1,54 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: repo-compare
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Mattia Roccoberton
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2021-06-06 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: Track changes of another repo.
14
+ email:
15
+ - mat@blocknot.es
16
+ executables:
17
+ - repo-compare
18
+ extensions: []
19
+ extra_rdoc_files: []
20
+ files:
21
+ - MIT-LICENSE
22
+ - README.md
23
+ - Rakefile
24
+ - bin/repo-compare
25
+ - lib/repo-compare/config.rb
26
+ - lib/repo-compare/git_diff.rb
27
+ - lib/repo-compare/git_diff_raw.rb
28
+ - lib/repo-compare/git_remote_update.rb
29
+ - lib/repo-compare/summary.rb
30
+ - lib/repo-compare/version.rb
31
+ homepage: https://github.com/blocknotes/repo-compare
32
+ licenses:
33
+ - MIT
34
+ metadata: {}
35
+ post_install_message:
36
+ rdoc_options: []
37
+ require_paths:
38
+ - lib
39
+ required_ruby_version: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ version: '0'
44
+ required_rubygems_version: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - ">="
47
+ - !ruby/object:Gem::Version
48
+ version: '0'
49
+ requirements: []
50
+ rubygems_version: 3.1.4
51
+ signing_key:
52
+ specification_version: 4
53
+ summary: Repo Compare
54
+ test_files: []