0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

SourceTree Mac 差分作成

Last updated at Posted at 2020-09-11

SourceTreeのカスタムアクションから選択範囲内の差分を出力する。

SourceTreeのパラメータは「$SHA」

権限変更が必要
chmod +x git-export-diff.rb

ファイル名
git-export-diff.rb

#!/usr/bin/env ruby
#
#= Export diff files on specific revisions
#
# Export diff files on specific revisions.
#
#= Usage
#
# git-export-diff.rb {hash}
#
# If you want to use with SourceTree, set custom action with argument $SHA
#
require "yaml"
require "optparse"
require 'shellwords'

root_path = Dir::pwd # get repository fill path without $REPO.
root_dir  = File.basename(root_path)

unless File.exists?(File.join(root_path, ".git"))
  puts "Oops! Current directory is not a git repository."
  exit 1
end

# default options
options = {
  :archive => nil,
  :output => File.join(root_path, "..")
}

# load config if exist
path_yml = File.join(root_path, "git-export-config.yml")
global_config = File.exists?(path_yml) ? YAML.load_file(path_yml) : {}
config = global_config['diff'] # FIXME: be more flexible

# overwrite options by values from yaml
if config
  [:archive, :output, :format].each do |k|
    options[k] = config[k.to_s] if config[k.to_s]
  end
end

# overwrite options by argument options
OptionParser.new do |opt|
  opt.on('-a VALUE', 'ARCHIVE FORMAT (zip, tar ,tgz, tar.gz)') do |v|
    options[:archive] = v if /(zip|tar|tgz|tar\.gz)/ === v
  end
  opt.on('-o VALUE', 'OUTPUT PATH') do |v|
    options[:output] = v
  end
  opt.on('-f VALUE', 'OUTPUT NAME FORMAT (ex. OUTPUT-%y%m%d)') do |v|
    options[:format] = v
  end
  opt.parse!(ARGV)
end



sha = ARGV.first # get last selected rev. newer commit
sha_old = ARGV.last  # get last selected rev. older commit

unless /[a-z0-9]{4,40}/ === sha and /[a-z0-9]{4,40}/ === sha_old
  puts "Give me valid SHA hash!"
  exit 1
end



# set previous hash to "from" if not selected multiple revision
sha_old = sha + "^" if sha_old === sha



if options[:format]
  dir = Time.now.strftime(options[:format])
else
  # get tag name or branch name
  desc = %x[git describe --contains --all #{sha}]
  name = case desc
    when /^tags/
      desc[/tags\/(\w+)\^0/, 1].strip
    when /^remotes/
      desc[/remotes\/(\w+\/\w+)/, 1].gsub("/", "-").strip + "-#{sha[0,7]}"
    else
      desc.sub(/~\d/, "").strip + "-#{sha[0,7]}"
    end

  dir = "#{root_dir}-#{name}"
end

output = File.join(options[:output], dir)

puts "sha\t: "     + "#{sha}"
puts "sha_old\t: " + "#{sha}"
puts "root\t: "    + "#{root_path}"
puts "name\t: "    + "#{name}"
puts "dir\t:  "    + "#{dir}"
puts "output\t: "  + "#{output}"

puts "---- options ----  "

options.keys.each do |k|
  puts "#{k.to_s}\t: #{options[k]}"
end



diff_cmd = "git diff --stat --diff-filter=ACRM --name-only #{sha_old}..#{sha}"
diff_files = %x[#{diff_cmd}]

puts "\n"
puts "---- export candidate files ----"
puts diff_files
puts "--------------------------------"
puts "\n"

if diff_files.empty?
  puts "There are no export files."
  exit 0
end



# suffix number if already exist file or directory
suffix_no = 0
suffix_format = "-%03d"
suffix = ""
ext = options[:archive] ? options[:archive] : ""

while File.exists?(output + suffix + ext)
  suffix_no = suffix_no + 1
  suffix = suffix_format % [suffix_no]
end
output = (output + suffix).shellescape

# for arguments
diff_files = diff_files.split("\n").join(" ")

cmd = case options[:archive]
  when /(zip|tar|tar\.gz|tgz)/
    %[git archive #{sha} --format=#{options[:archive]} --prefix=#{dir}/ -o #{output}.#{options[:archive]} -- #{diff_files}]
  else
    %[mkdir -p #{output}; git archive #{sha} -- #{diff_files} | tar -xC #{output}]
end

puts "cmd\t: " + cmd
%x[#{cmd}]

exit 0
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?