Guest User

Untitled

a guest
Feb 19th, 2019
36
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.36 KB | None | 0 0
  1. require 'digest/sha1'
  2. require 'zlib'
  3. require 'pp'
  4.  
  5. module Git
  6.  
  7. OBJECTS = {}
  8.  
  9. class Object
  10.  
  11. def initialize(content)
  12. @uncompressed_content = header(content) + content
  13. puts hash
  14. return hash
  15. end
  16.  
  17. def hash
  18. @sha1 ||= Digest::SHA1.hexdigest(@uncompressed_content)
  19. end
  20.  
  21. def compressed
  22. @compressed_content ||= Zlib::Deflate.deflate(@uncompressed_content)
  23. end
  24.  
  25. def path
  26. @path ||= ".git/objects/" + hash[0..1] + "/" + hash[2..-1]
  27. end
  28.  
  29. def header(type, content)
  30. "#{type} #{content.length}\0"
  31. end
  32.  
  33. def save
  34. OBJECTS[path.to_sym] ||= compressed
  35. end
  36.  
  37. end
  38.  
  39. class Blob < Object
  40.  
  41. def header(content)
  42. super("blob", content)
  43. end
  44.  
  45. def hash_bytes
  46. eval(hash.scan(/../).map {|p| "\x" + p.upcase}.join)
  47. end
  48.  
  49. end
  50.  
  51. class Tree < Object
  52.  
  53. def initialize(content)
  54. validate(content)
  55. super(content)
  56. end
  57.  
  58. def header(content)
  59. super("tree", content)
  60. end
  61.  
  62. private
  63.  
  64. def validate(content)
  65. # must be a list of trees and blobs
  66. #
  67. end
  68.  
  69. end
  70.  
  71. class Commit < Object
  72.  
  73. def initialize(content)
  74. validate(content)
  75. super(content)
  76. end
  77.  
  78. def header(content)
  79. super("commit", content)
  80. end
  81.  
  82. private
  83.  
  84. def validate(content)
  85. # must refer to a tree hash, zero or more parent commit hashes,
  86. # an author (with datetime), a commiter (with datetime), and a message
  87. end
  88.  
  89. end
  90.  
  91. class Tag < Object
  92. def initialize(content)
  93. validate(content)
  94. super(content)
  95. end
  96.  
  97. private
  98.  
  99. def validate(content)
  100. #tag must have an object hash, object type, tag name, tagger (with datetime), and message
  101. # example:
  102. #object 7e7b6a09dc5e466b7992fea125732c67239ac92b
  103. #type commit
  104. #tag v2.0
  105. #tagger Joe Schmo <jo.shmo@gmail.com> 1430542850 -0700
  106. #
  107. #tag test
  108. #
  109. end
  110.  
  111. def save
  112. super
  113. #and also add a file in .git/refs/tags whose name is the tag name and
  114. # whose content is the sha1 of the tag object created in the object store
  115. end
  116. end
  117.  
  118. end
  119.  
  120. # Every command in git either makes one or more objects in the database,
  121. # changes a reference, or displays an object or reference.
  122. # The only exception to this rule is modifying your config file.
  123.  
  124. # git add some_file.txt
  125. # results in the following:
  126. # a new blob is created, and added to the object store
  127. file_name = "some_file.txt"
  128. file_content = "some text in a file"
  129.  
  130. blob = Git::Blob.new(file_content)
  131. blob.save
  132. pp Git::OBJECTS
  133.  
  134. # it also adds the new blob to the index so that when you commit
  135. # the following tree is created
  136. tree_content = "100644 #{file_name}\x00#{blob.hash_bytes}"
  137.  
  138. tree = Git::Tree.new(tree_content)
  139. tree.save
  140. pp Git::OBJECTS
  141.  
  142. commit_content = (tree = "tree #{tree.hash}\n")
  143. commit_content += (author = "author Dominic Muller <nicklink483@gmail.com> 1430522440 -0700\n")
  144. commit_content += (committer = "committer Dominic Muller <nicklink483@gmail.com> 1430522440 -0700\n")
  145. commit_content += (message = "\nI'm a commit message!\n")
  146.  
  147. # git commit -m "I'm a commit message!"
  148. # this will now result in a commit object being created that points to that tree
  149. # that the index made for you.
  150. # The author and commiter will be grabbed from your config files
  151. commit = Git::Commit.new(commit_content)
  152. commit.save
  153. pp Git::OBJECTS
  154.  
  155. # congrats! Now the object store has 3 new key-value pairs. One blob, one tree, and one commit
  156. # The files are saved after being compressed with the zlib deflate compression.
  157. # so the key is the hash of the content of the object (including the header prepended),
  158. # and the value is the compressed content (including the header prepended).
  159.  
  160. # A branch is a reference to some commit
  161. # When you make your first commit, Git sets the master reference to point to its hash
  162.  
  163. master = commit.hash
  164.  
  165. # Git also sets a reference called HEAD to point to some branch.
  166. # Which in turn points at some commit hash, but we'll just use the branch name for now
  167. # let's make another commit!
  168.  
  169. file_content = "new file here!"
  170. file_name2 = "new_file.txt"
  171.  
  172. blob2 = Git::Blob.new(file_content)
  173. blob2.save
  174.  
  175. # and now to make a tree which has BOTH files so far
  176.  
  177. tree_content = (tree_file_1 = "100644 #{file_name}\x00#{blob.hash_bytes}")
  178. tree_content += (tree_file_2 = "100644 #{file_name2}\x00#{blob2.hash_bytes}")
  179.  
  180. second_tree = Git::Tree.new(tree_content)
  181. second_tree.save
  182.  
  183. # And of course, if we're going to make history,
  184. # we have to tell the new commit where he came from
  185. # which requires adding a parent line
  186.  
  187. new_commit_content = (tree = "tree #{second_tree.hash}\n")
  188. new_commit_content += (parent = "parent #{commit.hash}\n")
  189. new_commit_content += (author = "author Dominic Muller <nicklink483@gmail.com> 1430523736 -0700\n")
  190. new_commit_content += (committer = "committer Dominic Muller <nicklink483@gmail.com> 1430523736 -0700\n")
  191. new_commit_content += (message = "\nA second commit. I have a parent!\n")
  192.  
  193. new_commit = Git::Commit.new(new_commit_content)
  194. new_commit.save
  195. master = new_commit.hash
  196. pp Git::OBJECTS
  197.  
  198. # If we want, we can go re-inflate any compressed objects
  199.  
  200. compressed_commit = Git::OBJECTS[:".git/objects/#{new_commit.hash[0..1]}/#{new_commit.hash[2..-1]}"]
  201.  
  202. puts Zlib::Inflate.inflate(compressed_commit).split("\0")[1..-1].join
  203.  
  204. # btw, that last line is exactly what `git cat-file -p HEAD` would have done
Add Comment
Please, Sign In to add comment