comparison mercurial/hgweb/hgweb_mod.py @ 4228:c52b7176af94

hgweb: handle IOErrors and OSErrors during unbundle This allows the client to display a reasonable message to the user (e.g. "Permission denied: .hg/lock"), instead of the current "<url> does not appear to be an hg repository".
author Alexis S. L. Carvalho <alexis@cecm.usp.br>
date Fri, 16 Mar 2007 00:22:55 -0300
parents f5b9edf3390b
children 0d51eb296fb9 3f2e334937ce
comparison
equal deleted inserted replaced
4227:f5b9edf3390b 4228:c52b7176af94
1097 try: 1097 try:
1098 length = int(req.env['CONTENT_LENGTH']) 1098 length = int(req.env['CONTENT_LENGTH'])
1099 for s in util.filechunkiter(req, limit=length): 1099 for s in util.filechunkiter(req, limit=length):
1100 fp.write(s) 1100 fp.write(s)
1101 1101
1102 lock = self.repo.lock()
1103 try: 1102 try:
1104 if not check_heads(): 1103 lock = self.repo.lock()
1105 req.write('0\n') 1104 try:
1106 req.write(_('unsynced changes\n')) 1105 if not check_heads():
1107 return 1106 req.write('0\n')
1108 1107 req.write(_('unsynced changes\n'))
1109 fp.seek(0) 1108 return
1110 header = fp.read(6) 1109
1111 if not header.startswith("HG"): 1110 fp.seek(0)
1112 # old client with uncompressed bundle 1111 header = fp.read(6)
1113 def generator(f): 1112 if not header.startswith("HG"):
1114 yield header 1113 # old client with uncompressed bundle
1115 for chunk in f: 1114 def generator(f):
1116 yield chunk 1115 yield header
1117 elif not header.startswith("HG10"): 1116 for chunk in f:
1118 req.write("0\n") 1117 yield chunk
1119 req.write(_("unknown bundle version\n")) 1118 elif not header.startswith("HG10"):
1120 return 1119 req.write("0\n")
1121 elif header == "HG10GZ": 1120 req.write(_("unknown bundle version\n"))
1122 def generator(f): 1121 return
1123 zd = zlib.decompressobj() 1122 elif header == "HG10GZ":
1124 for chunk in f: 1123 def generator(f):
1125 yield zd.decompress(chunk) 1124 zd = zlib.decompressobj()
1126 elif header == "HG10BZ": 1125 for chunk in f:
1127 def generator(f): 1126 yield zd.decompress(chunk)
1128 zd = bz2.BZ2Decompressor() 1127 elif header == "HG10BZ":
1129 zd.decompress("BZ") 1128 def generator(f):
1130 for chunk in f: 1129 zd = bz2.BZ2Decompressor()
1131 yield zd.decompress(chunk) 1130 zd.decompress("BZ")
1132 elif header == "HG10UN": 1131 for chunk in f:
1133 def generator(f): 1132 yield zd.decompress(chunk)
1134 for chunk in f: 1133 elif header == "HG10UN":
1135 yield chunk 1134 def generator(f):
1135 for chunk in f:
1136 yield chunk
1137 else:
1138 req.write("0\n")
1139 req.write(_("unknown bundle compression type\n"))
1140 return
1141 gen = generator(util.filechunkiter(fp, 4096))
1142
1143 # send addchangegroup output to client
1144
1145 old_stdout = sys.stdout
1146 sys.stdout = cStringIO.StringIO()
1147
1148 try:
1149 url = 'remote:%s:%s' % (proto,
1150 req.env.get('REMOTE_HOST', ''))
1151 try:
1152 ret = self.repo.addchangegroup(
1153 util.chunkbuffer(gen), 'serve', url)
1154 except util.Abort, inst:
1155 sys.stdout.write("abort: %s\n" % inst)
1156 ret = 0
1157 finally:
1158 val = sys.stdout.getvalue()
1159 sys.stdout = old_stdout
1160 req.write('%d\n' % ret)
1161 req.write(val)
1162 finally:
1163 lock.release()
1164 except (OSError, IOError), inst:
1165 req.write('0\n')
1166 filename = getattr(inst, 'filename', '')
1167 # Don't send our filesystem layout to the client
1168 if filename.startswith(self.repo.root):
1169 filename = filename[len(self.repo.root)+1:]
1136 else: 1170 else:
1137 req.write("0\n") 1171 filename = ''
1138 req.write(_("unknown bundle compression type\n")) 1172 error = getattr(inst, 'strerror', 'Unknown error')
1139 return 1173 req.write('%s: %s\n' % (error, filename))
1140 gen = generator(util.filechunkiter(fp, 4096))
1141
1142 # send addchangegroup output to client
1143
1144 old_stdout = sys.stdout
1145 sys.stdout = cStringIO.StringIO()
1146
1147 try:
1148 url = 'remote:%s:%s' % (proto,
1149 req.env.get('REMOTE_HOST', ''))
1150 try:
1151 ret = self.repo.addchangegroup(util.chunkbuffer(gen),
1152 'serve', url)
1153 except util.Abort, inst:
1154 sys.stdout.write("abort: %s\n" % inst)
1155 ret = 0
1156 finally:
1157 val = sys.stdout.getvalue()
1158 sys.stdout = old_stdout
1159 req.write('%d\n' % ret)
1160 req.write(val)
1161 finally:
1162 lock.release()
1163 finally: 1174 finally:
1164 fp.close() 1175 fp.close()
1165 os.unlink(tempname) 1176 os.unlink(tempname)
1166 1177
1167 def do_stream_out(self, req): 1178 def do_stream_out(self, req):