Last active
November 14, 2016 15:00
-
-
Save denvazh/aeb410394659225ddfbec07481e70818 to your computer and use it in GitHub Desktop.
Script to show how git creates objects
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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