]> arthur.barton.de Git - bup.git/blob - cmd-server.py
More compile options for MacOS X.
[bup.git] / cmd-server.py
1 #!/usr/bin/env python2.5
2 import sys, struct, mmap
3 import options, git
4 from helpers import *
5
6
7 def init_dir(conn, arg):
8     git.init_repo(arg)
9     log('bup server: bupdir initialized: %r\n' % git.repodir)
10     conn.ok()
11
12
13 def set_dir(conn, arg):
14     git.check_repo_or_die(arg)
15     log('bup server: bupdir is %r\n' % git.repodir)
16     conn.ok()
17
18     
19 def list_indexes(conn, junk):
20     git.check_repo_or_die()
21     for f in os.listdir(git.repo('objects/pack')):
22         if f.endswith('.idx'):
23             conn.write('%s\n' % f)
24     conn.ok()
25
26
27 def send_index(conn, name):
28     git.check_repo_or_die()
29     assert(name.find('/') < 0)
30     assert(name.endswith('.idx'))
31     idx = git.PackIndex(git.repo('objects/pack/%s' % name))
32     conn.write(struct.pack('!I', len(idx.map)))
33     conn.write(idx.map)
34     conn.ok()
35     
36             
37 def receive_objects(conn, junk):
38     git.check_repo_or_die()
39     w = git.PackWriter()
40     while 1:
41         ns = conn.read(4)
42         if not ns:
43             w.abort()
44             raise Exception('object read: expected length header, got EOF\n')
45         n = struct.unpack('!I', ns)[0]
46         #log('expecting %d bytes\n' % n)
47         if not n:
48             log('bup server: received %d object%s.\n' 
49                 % (w.count, w.count!=1 and "s" or ''))
50             id = w.close()
51             conn.write('%s\n' % id)
52             conn.ok()
53             return
54         buf = conn.read(n)  # object sizes in bup are reasonably small
55         #log('read %d bytes\n' % n)
56         if len(buf) < n:
57             w.abort()
58             raise Exception('object read: expected %d bytes, got %d\n'
59                             % (n, len(buf)))
60         w._raw_write([buf])
61     # NOTREACHED
62
63
64 def read_ref(conn, refname):
65     git.check_repo_or_die()
66     r = git.read_ref(refname)
67     conn.write('%s\n' % (r or '').encode('hex'))
68     conn.ok()
69
70
71 def update_ref(conn, refname):
72     git.check_repo_or_die()
73     newval = conn.readline().strip()
74     oldval = conn.readline().strip()
75     git.update_ref(refname, newval.decode('hex'), oldval.decode('hex'))
76     conn.ok()
77
78
79 def cat(conn, id):
80     git.check_repo_or_die()
81     for blob in git.cat(id):
82         conn.write(struct.pack('!I', len(blob)))
83         conn.write(blob)
84     conn.write('\0\0\0\0')
85     conn.ok()
86
87
88 optspec = """
89 bup server
90 """
91 o = options.Options('bup server', optspec)
92 (opt, flags, extra) = o.parse(sys.argv[1:])
93
94 if extra:
95     log('bup server: no arguments expected\n')
96     o.usage()
97
98 log('bup server: reading from stdin.\n')
99
100 commands = {
101     'init-dir': init_dir,
102     'set-dir': set_dir,
103     'list-indexes': list_indexes,
104     'send-index': send_index,
105     'receive-objects': receive_objects,
106     'read-ref': read_ref,
107     'update-ref': update_ref,
108     'cat': cat,
109 }
110
111 # FIXME: this protocol is totally lame and not at all future-proof.
112 # (Especially since we abort completely as soon as *anything* bad happens)
113 conn = Conn(sys.stdin, sys.stdout)
114 lr = linereader(conn)
115 for _line in lr:
116     line = _line.strip()
117     if not line:
118         continue
119     log('bup server: command: %r\n' % line)
120     words = line.split(' ', 1)
121     cmd = words[0]
122     rest = len(words)>1 and words[1] or ''
123     if cmd == 'quit':
124         break
125     else:
126         cmd = commands.get(cmd)
127         if cmd:
128             cmd(conn, rest)
129         else:
130             raise Exception('unknown server command: %r\n' % line)
131
132 log('bup server: done\n')