##// END OF EJS Templates
Add an sshrepository class and hg serve --stdio
Matt Mackall -
r624:876333a2 default
parent child Browse files
Show More
@@ -9,7 +9,7 b' from demandload import *'
9 demandload(globals(), "os re sys signal")
9 demandload(globals(), "os re sys signal")
10 demandload(globals(), "fancyopts ui hg util")
10 demandload(globals(), "fancyopts ui hg util")
11 demandload(globals(), "hgweb mdiff random signal time traceback")
11 demandload(globals(), "hgweb mdiff random signal time traceback")
12 demandload(globals(), "errno socket version")
12 demandload(globals(), "errno socket version struct")
13
13
14 class UnknownCommand(Exception): pass
14 class UnknownCommand(Exception): pass
15
15
@@ -823,9 +823,67 b' def root(ui, repo):'
823
823
824 def serve(ui, repo, **opts):
824 def serve(ui, repo, **opts):
825 """export the repository via HTTP"""
825 """export the repository via HTTP"""
826
827 if opts["stdio"]:
828 def getarg():
829 argline = sys.stdin.readline()[:-1]
830 arg, l = argline.split()
831 val = sys.stdin.read(int(l))
832 return arg, val
833 def respond(v):
834 sys.stdout.write("%d\n" % len(v))
835 sys.stdout.write(v)
836 sys.stdout.flush()
837
838 while 1:
839 cmd = sys.stdin.readline()[:-1]
840 if cmd == '':
841 return
842 if cmd == "heads":
843 h = repo.heads()
844 respond(" ".join(map(hg.hex, h)) + "\n")
845 elif cmd == "branches":
846 arg, nodes = getarg()
847 nodes = map(hg.bin, nodes.split(" "))
848 r = []
849 for b in repo.branches(nodes):
850 r.append(" ".join(map(hg.hex, b)) + "\n")
851 respond("".join(r))
852 elif cmd == "between":
853 arg, pairs = getarg()
854 pairs = [ map(hg.bin, p.split("-")) for p in pairs.split(" ") ]
855 r = []
856 for b in repo.between(pairs):
857 r.append(" ".join(map(hg.hex, b)) + "\n")
858 respond("".join(r))
859 elif cmd == "changegroup":
860 nodes = []
861 arg, roots = getarg()
862 nodes = map(hg.bin, roots.split(" "))
863
864 b = []
865 t = 0
866 for chunk in repo.changegroup(nodes):
867 t += len(chunk)
868 b.append(chunk)
869 if t > 4096:
870 sys.stdout.write(struct.pack(">l", t))
871 for c in b:
872 sys.stdout.write(c)
873 t = 0
874 b = []
875
876 sys.stdout.write(struct.pack(">l", t))
877 for c in b:
878 sys.stdout.write(c)
879
880 sys.stdout.write(struct.pack(">l", -1))
881 sys.stdout.flush()
882
826 def openlog(opt, default):
883 def openlog(opt, default):
827 if opts[opt] and opts[opt] != '-': return open(opts[opt], 'w')
884 if opts[opt] and opts[opt] != '-': return open(opts[opt], 'w')
828 else: return default
885 else: return default
886
829 httpd = hgweb.create_server(repo.root, opts["name"], opts["templates"],
887 httpd = hgweb.create_server(repo.root, opts["name"], opts["templates"],
830 opts["address"], opts["port"],
888 opts["address"], opts["port"],
831 openlog('accesslog', sys.stdout),
889 openlog('accesslog', sys.stdout),
@@ -1017,6 +1075,7 b' table = {'
1017 ('p', 'port', 8000, 'listen port'),
1075 ('p', 'port', 8000, 'listen port'),
1018 ('a', 'address', '', 'interface address'),
1076 ('a', 'address', '', 'interface address'),
1019 ('n', 'name', os.getcwd(), 'repository name'),
1077 ('n', 'name', os.getcwd(), 'repository name'),
1078 ('', 'stdio', None, 'for remote clients'),
1020 ('t', 'templates', "", 'template map')],
1079 ('t', 'templates', "", 'template map')],
1021 "hg serve [options]"),
1080 "hg serve [options]"),
1022 "^status": (status, [], 'hg status'),
1081 "^status": (status, [], 'hg status'),
@@ -1592,6 +1592,88 b' class httprepository:'
1592 yield zd.decompress(d)
1592 yield zd.decompress(d)
1593 self.ui.note("%d bytes of data transfered\n" % bytes)
1593 self.ui.note("%d bytes of data transfered\n" % bytes)
1594
1594
1595 class sshrepository:
1596 def __init__(self, ui, path):
1597 self.url = path
1598 self.ui = ui
1599
1600 m = re.match(r'ssh://(([^@]+)@)?([^:/]+)(:(\d+))?(/(.*))?', path)
1601 if not m:
1602 raise RepoError("couldn't parse destination %s\n" % path)
1603
1604 self.user = m.group(2)
1605 self.host = m.group(3)
1606 self.port = m.group(5)
1607 self.path = m.group(7)
1608
1609 args = self.user and ("%s@%s" % (self.user, self.host)) or self.host
1610 args = self.port and ("%s -p %s") % (args, self.port) or args
1611 path = self.path or ""
1612
1613 cmd = "ssh %s 'hg -R %s serve --stdio'"
1614 cmd = cmd % (args, path)
1615
1616 self.pipeo, self.pipei = os.popen2(cmd)
1617
1618 def __del__(self):
1619 self.pipeo.close()
1620 self.pipei.close()
1621
1622 def do_cmd(self, cmd, **args):
1623 self.ui.debug("sending %s command\n" % cmd)
1624 self.pipeo.write("%s\n" % cmd)
1625 for k, v in args.items():
1626 self.pipeo.write("%s %d\n" % (k, len(v)))
1627 self.pipeo.write(v)
1628 self.pipeo.flush()
1629
1630 return self.pipei
1631
1632 def call(self, cmd, **args):
1633 r = self.do_cmd(cmd, **args)
1634 l = int(r.readline())
1635 return r.read(l)
1636
1637 def heads(self):
1638 d = self.call("heads")
1639 try:
1640 return map(bin, d[:-1].split(" "))
1641 except:
1642 self.ui.warn("unexpected response:\n" + d[:400] + "\n...\n")
1643 raise
1644
1645 def branches(self, nodes):
1646 n = " ".join(map(hex, nodes))
1647 d = self.call("branches", nodes=n)
1648 try:
1649 br = [ tuple(map(bin, b.split(" "))) for b in d.splitlines() ]
1650 return br
1651 except:
1652 self.ui.warn("unexpected response:\n" + d[:400] + "\n...\n")
1653 raise
1654
1655 def between(self, pairs):
1656 n = "\n".join(["-".join(map(hex, p)) for p in pairs])
1657 d = self.call("between", pairs=n)
1658 try:
1659 p = [ l and map(bin, l.split(" ")) or [] for l in d.splitlines() ]
1660 return p
1661 except:
1662 self.ui.warn("unexpected response:\n" + d[:400] + "\n...\n")
1663 raise
1664
1665 def changegroup(self, nodes):
1666 n = " ".join(map(hex, nodes))
1667 f = self.do_cmd("changegroup", roots=n)
1668 bytes = 0
1669 while 1:
1670 l = struct.unpack(">l", f.read(4))[0]
1671 if l == -1: break
1672 d = f.read(l)
1673 bytes += len(d)
1674 yield d
1675 self.ui.note("%d bytes of data transfered\n" % bytes)
1676
1595 def repository(ui, path=None, create=0):
1677 def repository(ui, path=None, create=0):
1596 if path:
1678 if path:
1597 if path.startswith("http://"):
1679 if path.startswith("http://"):
@@ -1600,5 +1682,7 b' def repository(ui, path=None, create=0):'
1600 return httprepository(ui, path.replace("hg://", "http://"))
1682 return httprepository(ui, path.replace("hg://", "http://"))
1601 if path.startswith("old-http://"):
1683 if path.startswith("old-http://"):
1602 return localrepository(ui, path.replace("old-http://", "http://"))
1684 return localrepository(ui, path.replace("old-http://", "http://"))
1685 if path.startswith("ssh://"):
1686 return sshrepository(ui, path)
1603
1687
1604 return localrepository(ui, path, create)
1688 return localrepository(ui, path, create)
General Comments 0
You need to be logged in to leave comments. Login now