repo-compare 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +57 -0
- data/Rakefile +16 -0
- data/bin/repo-compare +55 -0
- data/lib/repo-compare/config.rb +42 -0
- data/lib/repo-compare/git_diff.rb +25 -0
- data/lib/repo-compare/git_diff_raw.rb +51 -0
- data/lib/repo-compare/git_remote_update.rb +20 -0
- data/lib/repo-compare/summary.rb +35 -0
- data/lib/repo-compare/version.rb +5 -0
- metadata +54 -0
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
|
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: []
|