Last active
October 10, 2017 22:48
-
-
Save jcoglan/a82001bb5e01173678dd7326ccbf07ab to your computer and use it in GitHub Desktop.
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
Blob = Struct.new(:oid, :content) do | |
def type | |
Database::BLOB | |
end | |
def to_s | |
content | |
end | |
end |
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
Commit = Struct.new(:oid, :tree, :message) do | |
def type | |
Database::COMMIT | |
end | |
def to_s | |
["tree #{ tree.oid }", "", message].join("\n") | |
end | |
end |
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
require "digest/sha1" | |
require "fileutils" | |
require "zlib" | |
require_relative "./blob" | |
require_relative "./tree" | |
require_relative "./commit" | |
class Database | |
BLOB = "blob" | |
TREE = "tree" | |
COMMIT = "commit" | |
def initialize(pathname) | |
@pathname = pathname | |
end | |
def store(object) | |
string = object.to_s.force_encoding(Encoding::ASCII_8BIT) | |
content = "#{ object.type } #{ string.bytesize }\0#{ string }" | |
object.oid = Digest::SHA1.hexdigest(content) | |
write_file(object.oid, content) | |
end | |
def write_file(oid, content) | |
path = @pathname.join(oid[0..1], oid[2..-1]) | |
FileUtils.mkdir_p(path.dirname) | |
File.write(path, Zlib::Deflate.deflate(content)) | |
end | |
end |
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
require "fileutils" | |
require "pathname" | |
require_relative "./database" | |
require_relative "./workspace" | |
work_path = Pathname.new(Dir.getwd) | |
workspace = Workspace.new(work_path) | |
git_path = work_path.join(".git") | |
database = Database.new(git_path.join("objects")) | |
%w[objects refs].each do |dir| | |
FileUtils.mkdir_p(git_path.join(dir)) | |
end | |
source_files = workspace.list_files | |
entries = source_files.map do |path| | |
data = workspace.read_file(path) | |
stat = workspace.stat_file(path) | |
blob = Blob.new(nil, data) | |
database.store(blob) | |
[stat, blob, path] | |
end | |
tree = Tree.new(nil, entries) | |
database.store(tree) | |
message = "Just enough code to write a commit." | |
commit = Commit.new(nil, tree, message) | |
database.store(commit) | |
File.open(git_path.join("HEAD"), "w") { |file| file.puts(commit.oid) } |
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
Tree = Struct.new(:oid, :entries) do | |
def type | |
Database::TREE | |
end | |
def to_s | |
entries.sort_by!(&:last) | |
lines = entries.map do |stat, blob, path| | |
["100644", path, blob.oid].pack("A7Z*H40") | |
end | |
lines.join("") | |
end | |
end |
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
class Workspace | |
IGNORE = %w[. .. .git] | |
def initialize(pathname) | |
@pathname = pathname | |
end | |
def list_files | |
Dir.entries(@pathname) - IGNORE | |
end | |
def read_file(path) | |
File.read(@pathname.join(path)) | |
end | |
def stat_file(path) | |
File.stat(@pathname.join(path)) | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment