Owner:@Shuhan6017
Module: 4 - Remotes & networking
File you own:minigit/remote.py
Week: 2 of 10 - Real Bytes on Disk
What changes this week
- Week 1 was a sketch in comments
- Week 2 a real TCP socket opens, a real handshake runs, and it either authenticates or errors
- object transfer is still stubbed -> Week 6
Wire protocol - now real
- one message per line, UTF-8,
\n-terminated - client:
AUTH <token> / REF <branch> / WANT <hash> / DONE - server:
OK / REF <branch> <hash|-> / OBJ <type> <len> / ERR <reason> - any
ERR line, any timeout, any dropped connection -> NetworkProtocolError
Steps
- Branch
week2/m4-tcp-handshake - Line helpers (module-level, they get reused everywhere):
send_line(sock, text) -> sock.sendall((text + "\n").encode())recv_line(sock, buf) -> read until \n, return the line without it; connection closed mid-line -> NetworkProtocolError- keep a leftover buffer - one
recv() can return two lines or half of one
RemoteServer class in the same file:
__init__(self, repo_path=".", token="", host="127.0.0.1", port=0)- port
0 = OS picks a free port; expose the real one as self.port (that's how tests get one) serve_forever() -> accept, handle one client at a time, never crash the process on a bad client- handler: first line must be
AUTH <token> and match -> OK, else ERR bad auth and close - then
REF <branch> -> reply REF <branch> <hash>, or REF <branch> - when the branch has no commits - read the branch hash off disk from
.minigit/refs/heads/<branch>
push(remote_address, branch, token):
- parse address, empty token ->
NetworkProtocolError (Week 1 behaviour, keep it) socket.create_connection((host, port), timeout=5), try/finally: sock.close()- send
AUTH, expect OK - send
REF <branch>, read the remote hash - print
remote <branch> is at <hash> then # Week 6 - send missing objects, move the ref last
pull -> same handshake, print the remote hash, stop there # Week 6- New command
minigit serve --port <n> --token <t> -> starts RemoteServer, prints listening on <host>:<port> - Do NOT: add a dependency, thread the object transfer, or handle more than one client at a time
- Tests
tests/test_remote.py:
- keep every Week 1
_parse_address test - fixture: start
RemoteServer(port=0) on a threading.Thread(daemon=True) against a tmp_path repo, yield the port, shut it down after - correct token ->
push does not raise - wrong token ->
NetworkProtocolError - branch with a commit -> the printed hash matches the ref file
- branch that doesn't exist ->
-, no raise - closed port ->
NetworkProtocolError not ConnectionRefusedError recv_line handles two lines arriving in one packet
- quality-check green -> commit, push, PR
Notes
- always bind
127.0.0.1, never 0.0.0.0 - this is a class project on someone's laptop - token in plaintext over TCP is deliberately not secure; that's a Week 9 conversation, not now
- tests must never hardcode a port number - CI runs them in parallel
Done when
Owner:@Shuhan6017
Module: 4 - Remotes & networking
File you own:
minigit/remote.pyWeek: 2 of 10 - Real Bytes on Disk
What changes this week
Wire protocol - now real
\n-terminatedAUTH <token>/REF <branch>/WANT <hash>/DONEOK/REF <branch> <hash|->/OBJ <type> <len>/ERR <reason>ERRline, any timeout, any dropped connection ->NetworkProtocolErrorSteps
week2/m4-tcp-handshakesend_line(sock, text)->sock.sendall((text + "\n").encode())recv_line(sock, buf)-> read until\n, return the line without it; connection closed mid-line ->NetworkProtocolErrorrecv()can return two lines or half of oneRemoteServerclass in the same file:__init__(self, repo_path=".", token="", host="127.0.0.1", port=0)0= OS picks a free port; expose the real one asself.port(that's how tests get one)serve_forever()-> accept, handle one client at a time, never crash the process on a bad clientAUTH <token>and match ->OK, elseERR bad authand closeREF <branch>-> replyREF <branch> <hash>, orREF <branch> -when the branch has no commits.minigit/refs/heads/<branch>push(remote_address, branch, token):NetworkProtocolError(Week 1 behaviour, keep it)socket.create_connection((host, port), timeout=5),try/finally: sock.close()AUTH, expectOKREF <branch>, read the remote hashremote <branch> is at <hash>then# Week 6 - send missing objects, move the ref lastpull-> same handshake, print the remote hash, stop there# Week 6minigit serve --port <n> --token <t>-> startsRemoteServer, printslistening on <host>:<port>tests/test_remote.py:_parse_addresstestRemoteServer(port=0)on athreading.Thread(daemon=True)against atmp_pathrepo, yield the port, shut it down afterpushdoes not raiseNetworkProtocolError-, no raiseNetworkProtocolErrornotConnectionRefusedErrorrecv_linehandles two lines arriving in one packetNotes
127.0.0.1, never0.0.0.0- this is a class project on someone's laptopDone when
send_line/recv_linehandle partial and batched readsRemoteServerdoes AUTH + REF over a real socketpush/pullcomplete the handshake and report the remote hashNetworkProtocolErrorminigit serveruns