1
+ import hashlib
1
2
import os
2
3
import shutil
3
4
import subprocess
5
+ import zlib
6
+
7
+ git_dir = b'.git'
8
+ objects_dir = os .path .join (git_dir , b'objects' )
9
+
10
+ # Tree parameters.
11
+ default_blob_basename = b'a'
12
+ default_blob_content = b'a'
13
+ default_blob_mode = b'100644'
14
+
15
+ # Commit parameters.
16
+ default_name = b'a'
17
+ default_email = b'a@a.com'
18
+ # 2000-01-01T00:00:00+0000
19
+ default_date_s = 946684800
20
+ default_date_format = b'%s +0000'
21
+ default_date = b'%s +0000' % str (default_date_s ).encode ('ascii' )
22
+ default_author_date = default_date
23
+ default_author_email = default_email
24
+ default_author_name = default_name
25
+ default_committer_date = default_date
26
+ default_committer_email = default_email
27
+ default_committer_name = default_name
28
+ default_message = b'a'
29
+ # ASCII hex of parents.
30
+ default_parents = ()
4
31
5
32
def init ():
6
33
repo = 'repo.tmp'
@@ -9,3 +36,64 @@ def init():
9
36
os .mkdir (repo )
10
37
os .chdir (repo )
11
38
subprocess .check_output (['git' , 'init' , '-q' ])
39
+
40
+ def get_object_and_sha (obj_type , content ):
41
+ obj = b'%s %s\0 %s' % (obj_type , str (len (content )).encode ('ascii' ), content )
42
+ hash = hashlib .sha1 (obj )
43
+ return (obj , hash .hexdigest ().encode ('ascii' ), hash .digest ())
44
+
45
+ def save_object (obj_type , content ):
46
+ obj , sha_ascii , sha = get_object_and_sha (obj_type , content )
47
+ obj_dir = os .path .join (objects_dir , sha_ascii [:2 ])
48
+ obj_path = os .path .join (obj_dir , sha_ascii [2 :])
49
+ os .makedirs (obj_dir , exist_ok = True )
50
+ with open (obj_path , 'wb' ) as f :
51
+ f .write (zlib .compress (obj ))
52
+ return sha_ascii , sha
53
+
54
+ # TODO multiple children object.
55
+ def save_tree_object (mode , basename , sha ):
56
+ tree_content = b'%s %s\0 %s' % (mode , basename , sha )
57
+ return save_object (b'tree' , tree_content ) + (tree_content ,)
58
+
59
+ def save_commit_object (
60
+ tree_sha_ascii ,
61
+ parents = default_parents ,
62
+ author_name = default_author_name ,
63
+ author_email = default_author_email ,
64
+ author_date = default_author_date ,
65
+ committer_name = default_committer_name ,
66
+ committer_email = default_committer_email ,
67
+ committer_date = default_committer_date ,
68
+ message = default_message ):
69
+ if parents :
70
+ parents_bytes = b''
71
+ sep = b'\n parent '
72
+ parents_bytes = sep + sep .join (parents ) + b'\n '
73
+ else :
74
+ parents_bytes = b'\n '
75
+ commit_content = b'tree %s%sauthor %s <%s> %s\n committer %s <%s> %s\n \n %s\n ' % (
76
+ tree_sha_ascii , parents_bytes ,
77
+ author_name , author_email , author_date ,
78
+ committer_name , committer_email , committer_date ,
79
+ message )
80
+ return save_object (b'commit' , commit_content ) + (commit_content ,)
81
+
82
+ def get_git_hash_object (obj_type , input ):
83
+ cmd = [b'git' , b'hash-object' , b'--stdin' , b'-t' , obj_type ]
84
+ return subprocess .check_output (cmd , input = input ).rstrip ()
85
+
86
+ def create_master (commit_sha_ascii ):
87
+ subprocess .check_output (['git' , 'branch' , 'master' , commit_sha_ascii ])
88
+
89
+ def clone ():
90
+ subprocess .check_output (['git' , 'clone' , '-q' , '.' , '../clone.tmp' ])
91
+
92
+ def create_tree_with_one_file (
93
+ blob_mode = default_blob_mode ,
94
+ blob_basename = default_blob_basename ,
95
+ blob_content = default_blob_content ,
96
+ ):
97
+ blob_sha_ascii , blob_sha = save_object (b'blob' , blob_content )
98
+ tree_sha_ascii , tree_sha , tree_content = save_tree_object (blob_mode , blob_basename , blob_sha )
99
+ return tree_sha_ascii
0 commit comments