Fix typos.
[jelmer/dulwich-libgit2.git] / dulwich / protocol.py
1 # protocol.py -- Shared parts of the git protocols
2 # Copryight (C) 2008 John Carr <john.carr@unrouted.co.uk>
3 # Copyright (C) 2008 Jelmer Vernooij <jelmer@samba.org>
4 #
5 # This program is free software; you can redistribute it and/or
6 # modify it under the terms of the GNU General Public License
7 # as published by the Free Software Foundation; version 2
8 # of the License.
9 #
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 # GNU General Public License for more details.
14 #
15 # You should have received a copy of the GNU General Public License
16 # along with this program; if not, write to the Free Software
17 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18 # MA  02110-1301, USA.
19
20 TCP_GIT_PORT = 9418
21
22 class ProtocolFile(object):
23     """
24     Some network ops are like file ops. The file ops expect to operate on
25     file objects, so provide them with a dummy file.
26     """
27
28     def __init__(self, read, write):
29         self.read = read
30         self.write = write
31
32     def tell(self):
33         pass
34
35     def close(self):
36         pass
37
38
39 class Protocol(object):
40
41     def __init__(self, read, write):
42         self.read = read
43         self.write = write
44
45     def read_pkt_line(self):
46         """
47         Reads a 'pkt line' from the remote git process
48
49         :return: The next string from the stream
50         """
51         sizestr = self.read(4)
52         if not sizestr:
53             return None
54         size = int(sizestr, 16)
55         if size == 0:
56             return None
57         return self.read(size-4)
58
59     def read_pkt_seq(self):
60         pkt = self.read_pkt_line()
61         while pkt:
62             yield pkt
63             pkt = self.read_pkt_line()
64
65     def write_pkt_line(self, line):
66         """
67         Sends a 'pkt line' to the remote git process
68
69         :param line: A string containing the data to send
70         """
71         if line is None:
72             self.write("0000")
73         else:
74             self.write("%04x%s" % (len(line)+4, line))
75
76     def write_sideband(self, channel, blob):
77         """
78         Write data to the sideband (a git multiplexing method)
79
80         :param channel: int specifying which channel to write to
81         :param blob: a blob of data (as a string) to send on this channel
82         """
83         # a pktline can be a max of 65535. a sideband line can therefore be
84         # 65535-5 = 65530
85         # WTF: Why have the len in ASCII, but the channel in binary.
86         while blob:
87             self.write_pkt_line("%s%s" % (chr(channel), blob[:65530]))
88             blob = blob[65530:]
89
90     def send_cmd(self, cmd, *args):
91         """
92         Send a command and some arguments to a git server
93
94         Only used for git://
95
96         :param cmd: The remote service to access
97         :param args: List of arguments to send to remove service
98         """
99         self.write_pkt_line("%s %s" % (cmd, "".join(["%s\0" % a for a in args])))
100
101     def read_cmd(self):
102         """
103         Read a command and some arguments from the git client
104
105         Only used for git://
106
107         :return: A tuple of (command, [list of arguments])
108         """
109         line = self.read_pkt_line()
110         splice_at = line.find(" ")
111         cmd, args = line[:splice_at], line[splice_at+1:]
112         return cmd, args.split(chr(0))
113  
114
115 def extract_capabilities(text):
116     if not "\0" in text:
117         return text, None
118     capabilities = text.split("\0")
119     return (capabilities[0], capabilities[1:])
120