Recently, I’ve been doing some patching on fpm and today I also started writing some tests for the changes I made. One change required that the gem in the repository used for testing had a bin in it so I modified the .gemspec and rebuild it.
After building and about to push it, I thought on how it must seem to the maintainer when somebody sends a pull request for a binary blob. I would like to know what really changed in there without having to go checkout the internals myself. How wonderful would life be if we could just use git diff to show the differences.
Here is a way to do just that using .gitattributes and a little shell script:
misc/gemdiff.sh:
#!/bin/bash
echo "============== metadata =============="
tar -xOf $1 metadata.gz 2>/dev/null | gunzip -c 2>/dev/null
echo "============== checksums ============="
tar -xOf $1 checksums.yaml.gz 2>/dev/null | gunzip -c 2>/dev/null
echo "=============== files ================"
tar -xOf $1 data.tar.gz 2>/dev/null | tar -xvOzf - 2>&1 |
#!/bin/bash
echo "============== metadata =============="
tar -xOf $1 metadata.gz 2>/dev/null | gunzip -c 2>/dev/null
echo "============== checksums ============="
tar -xOf $1 checksums.yaml.gz 2>/dev/null | gunzip -c 2>/dev/null
echo "=============== files ================"
tar -xOf $1 data.tar.gz 2>/dev/null | tar -xvOzf - 2>&1
.gitattributes:
*.gem diff=gemdiff
.git/config:
[diff "gemdiff"]
textconv = misc/gemdiff.sh
The result looks like this:
diff --git a/spec/fixtures/gem/example/example-1.0.gem b/spec/fixtures/gem/example/example-1.0.gem
index 0241779..f762e52 100644
--- a/spec/fixtures/gem/example/example-1.0.gem
+++ b/spec/fixtures/gem/example/example-1.0.gem
@@ -3,19 +3,17 @@
name: example
version: !ruby/object:Gem::Version
version: '1.0'
- prerelease:
platform: ruby
authors:
- sample author
autorequire:
bindir: bin
cert_chain: []
-date: 2012-03-15 00:00:00.000000000 Z
+date: 2014-05-01 00:00:00.000000000 Z
dependencies:
- !ruby/object:Gem::Dependency
name: dependency1
requirement: !ruby/object:Gem::Requirement
- none: false
requirements:
- - ! '>='
- !ruby/object:Gem::Version
@@ -23,7 +21,6 @@ dependencies:
type: :runtime
prerelease: false
version_requirements: !ruby/object:Gem::Requirement
- none: false
requirements:
- - ! '>='
- !ruby/object:Gem::Version
@@ -31,7 +28,6 @@ dependencies:
- !ruby/object:Gem::Dependency
name: dependency2
requirement: !ruby/object:Gem::Requirement
- none: false
requirements:
- - ! '>='
- !ruby/object:Gem::Version
@@ -39,42 +35,59 @@ dependencies:
type: :runtime
prerelease: false
version_requirements: !ruby/object:Gem::Requirement
- none: false
requirements:
- - ! '>='
- !ruby/object:Gem::Version
version: '0'
description: sample description
email: sample email
-executables: []
+executables:
+- example
extensions: []
extra_rdoc_files: []
-files: []
+files:
+- bin/example
homepage: http://sample-url/
licenses: []
+metadata: {}
post_install_message:
rdoc_options: []
require_paths:
- lib
required_ruby_version: !ruby/object:Gem::Requirement
- none: false
requirements:
- - ! '>='
- !ruby/object:Gem::Version
version: '0'
required_rubygems_version: !ruby/object:Gem::Requirement
- none: false
requirements:
- - ! '>='
- !ruby/object:Gem::Version
version: '0'
requirements: []
rubyforge_project:
-rubygems_version: 1.8.18
+rubygems_version: 2.0.14
signing_key:
-specification_version: 3
+specification_version: 4
summary: sample summary
test_files: []
has_rdoc:
============== checksums =============
+---
+!binary "U0hBMQ==":
+ metadata.gz: !binary |-
+ MjYwNGQ5MDZjYTE0MjY5MWQyZTA5Yzk0MjgyYjk2ZGM0ZTk3YzE3Mw==
+ data.tar.gz: !binary |-
+ YmZmYzJlNDU0ZGNmMDEzZjJmZGExYWZiYWE2ZjBjYTQ2MTMzYzFkNA==
+!binary "U0hBNTEy":
+ metadata.gz: !binary |-
+ MzYyYTVlNDk0ODRiNzdhNDBjOWE0ZmEyOGM0NjAzNzg3M2VlZTA4MzgzZDAw
+ ZjVhMjc5ZjFjYTIzOTk2MWFhYjZmMjNiNmVkNzRlMzMzMTdiOTMxMzlmM2Nl
+ ZGE3ZDc5ZDRkNjUwNDE1ODkzNDkxNDhmNmI5YmUyYjg2NjEwMjk=
+ data.tar.gz: !binary |-
+ MGY3NzllNTgwOGQ2YzhmOGUwNjlkMTk5NTlhOTIzZjJkZTkyMjdiNzQxZDQ3
+ NDc4ZjU5NGU1YTA4ODc1NzQwNTc3OWNlOWZkZjMwNWFmMDE3MWE4ZDUzNGY3
+ NDE0NGVmMjA4MDM1MDA4ZjdiMzliNWIwYTNiNDVkMWExZmIyYTY=
=============== files ================
+bin/example
+#!/usr/bin/env ruby |
diff --git a/spec/fixtures/gem/example/example-1.0.gem b/spec/fixtures/gem/example/example-1.0.gem
index 0241779..f762e52 100644
--- a/spec/fixtures/gem/example/example-1.0.gem
+++ b/spec/fixtures/gem/example/example-1.0.gem
@@ -3,19 +3,17 @@
name: example
version: !ruby/object:Gem::Version
version: '1.0'
- prerelease:
platform: ruby
authors:
- sample author
autorequire:
bindir: bin
cert_chain: []
-date: 2012-03-15 00:00:00.000000000 Z
+date: 2014-05-01 00:00:00.000000000 Z
dependencies:
- !ruby/object:Gem::Dependency
name: dependency1
requirement: !ruby/object:Gem::Requirement
- none: false
requirements:
- - ! '>='
- !ruby/object:Gem::Version
@@ -23,7 +21,6 @@ dependencies:
type: :runtime
prerelease: false
version_requirements: !ruby/object:Gem::Requirement
- none: false
requirements:
- - ! '>='
- !ruby/object:Gem::Version
@@ -31,7 +28,6 @@ dependencies:
- !ruby/object:Gem::Dependency
name: dependency2
requirement: !ruby/object:Gem::Requirement
- none: false
requirements:
- - ! '>='
- !ruby/object:Gem::Version
@@ -39,42 +35,59 @@ dependencies:
type: :runtime
prerelease: false
version_requirements: !ruby/object:Gem::Requirement
- none: false
requirements:
- - ! '>='
- !ruby/object:Gem::Version
version: '0'
description: sample description
email: sample email
-executables: []
+executables:
+- example
extensions: []
extra_rdoc_files: []
-files: []
+files:
+- bin/example
homepage: http://sample-url/
licenses: []
+metadata: {}
post_install_message:
rdoc_options: []
require_paths:
- lib
required_ruby_version: !ruby/object:Gem::Requirement
- none: false
requirements:
- - ! '>='
- !ruby/object:Gem::Version
version: '0'
required_rubygems_version: !ruby/object:Gem::Requirement
- none: false
requirements:
- - ! '>='
- !ruby/object:Gem::Version
version: '0'
requirements: []
rubyforge_project:
-rubygems_version: 1.8.18
+rubygems_version: 2.0.14
signing_key:
-specification_version: 3
+specification_version: 4
summary: sample summary
test_files: []
has_rdoc:
============== checksums =============
+---
+!binary "U0hBMQ==":
+ metadata.gz: !binary |-
+ MjYwNGQ5MDZjYTE0MjY5MWQyZTA5Yzk0MjgyYjk2ZGM0ZTk3YzE3Mw==
+ data.tar.gz: !binary |-
+ YmZmYzJlNDU0ZGNmMDEzZjJmZGExYWZiYWE2ZjBjYTQ2MTMzYzFkNA==
+!binary "U0hBNTEy":
+ metadata.gz: !binary |-
+ MzYyYTVlNDk0ODRiNzdhNDBjOWE0ZmEyOGM0NjAzNzg3M2VlZTA4MzgzZDAw
+ ZjVhMjc5ZjFjYTIzOTk2MWFhYjZmMjNiNmVkNzRlMzMzMTdiOTMxMzlmM2Nl
+ ZGE3ZDc5ZDRkNjUwNDE1ODkzNDkxNDhmNmI5YmUyYjg2NjEwMjk=
+ data.tar.gz: !binary |-
+ MGY3NzllNTgwOGQ2YzhmOGUwNjlkMTk5NTlhOTIzZjJkZTkyMjdiNzQxZDQ3
+ NDc4ZjU5NGU1YTA4ODc1NzQwNTc3OWNlOWZkZjMwNWFmMDE3MWE4ZDUzNGY3
+ NDE0NGVmMjA4MDM1MDA4ZjdiMzliNWIwYTNiNDVkMWExZmIyYTY=
=============== files ================
+bin/example
+#!/usr/bin/env ruby
Life.wonderfulness++;