Skip to content

Instantly share code, notes, and snippets.

@denvazh
Last active November 14, 2016 15:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save denvazh/aeb410394659225ddfbec07481e70818 to your computer and use it in GitHub Desktop.
Save denvazh/aeb410394659225ddfbec07481e70818 to your computer and use it in GitHub Desktop.
Script to show how git creates objects
#!/usr/bin/env ruby
# Based on code from: https://git-scm.com/book/en/v2/Git-Internals-Git-Objects#Object-Storage
require 'digest/sha1'
require 'fileutils'
require 'zlib'
require 'optparse'
require 'ostruct'
def gen_header(content)
"blob #{content.length}\0"
end
def calc_hash(str)
Digest::SHA1.hexdigest(str)
end
def gen_path(repo, sha1)
File.join(repo, '.git/objects', sha1[0,2], sha1[2,38])
end
# parse command-line options
class OptParser
def self.parse(argv)
options = OpenStruct.new
opt_parser = OptionParser.new do |opts|
opts.banner = 'Usage: hash-object.rb [options]'
opts.on('-f', '--file FILENAME', String, 'File to read the object from') do |file|
options[:file] = file
end
opts.on('-r', '--repo REPOSITORY', String, 'Path to the repository' ) do |repo|
options[:repo] = repo
end
opts.on_tail('-h', '--help', 'Show this message') do
puts opts
exit
end
end
begin
opt_parser.parse!(argv)
options
rescue OptionParser::InvalidOption, OptionParser::MissingArgument => err
puts err
puts opt_parser
exit 2
end
end
end
ARGV << '-h' if ARGV.empty?
options = OptParser.parse(ARGV)
if options.file.nil? || options.repo.nil?
puts 'Required options missing'
exit 2
end
unless Dir.exists?(File.join(options.repo, '.git'))
puts "\"#{options.repo}\" not a git repository"
exit 2
end
# read content from the given file
content = File.read(options.file)
# concatenate calculated header with actual file content
store = gen_header(content) + content
# calculate sha1 hash
sha1 = calc_hash(store)
# compress content
compressed_w_zlib = Zlib::Deflate.deflate(store)
# generate path where new blob object should be stored
path = gen_path(options.repo, sha1)
# create directory for path above
FileUtils.mkdir_p(File.dirname(path))
# write object to the disk
File.write(path, compressed_w_zlib)
# print sha1 hash to stdout
puts sha1
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment