comparison fetch_command.py @ 129:59f8603a6641

fetch_command: in stupid mode, load file content on demand
author Patrick Mezard <pmezard@gmail.com>
date Wed, 10 Dec 2008 11:03:21 -0600
parents bab5bcbbb3dc
children 2242dd1163c6
comparison
equal deleted inserted replaced
128:bab5bcbbb3dc 129:59f8603a6641
178 patchfile.__init__(self, ui, fname, None, False) 178 patchfile.__init__(self, ui, fname, None, False)
179 179
180 def readlines(self, fname): 180 def readlines(self, fname):
181 if fname not in parentctx: 181 if fname not in parentctx:
182 raise IOError('Cannot find %r to patch' % fname) 182 raise IOError('Cannot find %r to patch' % fname)
183 return cStringIO.StringIO(parentctx[fname].data()).readlines() 183 fctx = parentctx[fname]
184 data = fctx.data()
185 if 'l' in fctx.flags():
186 data = 'link ' + data
187 return cStringIO.StringIO(data).readlines()
184 188
185 def writelines(self, fname, lines): 189 def writelines(self, fname, lines):
186 files[fname] = ''.join(lines) 190 files[fname] = ''.join(lines)
187 191
188 def unlink(self, fname): 192 def unlink(self, fname):
224 if (hasattr(e, 'apr_err') and e.apr_err != 160013): 228 if (hasattr(e, 'apr_err') and e.apr_err != 160013):
225 raise 229 raise
226 raise BadPatchApply('previous revision does not exist') 230 raise BadPatchApply('previous revision does not exist')
227 files_data = {} 231 files_data = {}
228 binary_files = {} 232 binary_files = {}
233 touched_files = {}
229 for m in binary_file_re.findall(d): 234 for m in binary_file_re.findall(d):
230 # we have to pull each binary file by hand as a fulltext, 235 # we have to pull each binary file by hand as a fulltext,
231 # which sucks but we've got no choice 236 # which sucks but we've got no choice
232 binary_files[m] = 1 237 binary_files[m] = 1
233 files_data[m] = '' 238 touched_files[m] = 1
234 d2 = empty_file_patch_wont_make_re.sub('', d) 239 d2 = empty_file_patch_wont_make_re.sub('', d)
235 d2 = property_exec_set_re.sub('', d2) 240 d2 = property_exec_set_re.sub('', d2)
236 d2 = property_exec_removed_re.sub('', d2) 241 d2 = property_exec_removed_re.sub('', d2)
237 for f in any_file_re.findall(d): 242 for f in any_file_re.findall(d):
238 if f in files_data:
239 continue
240 # Here we ensure that all files, including the new empty ones 243 # Here we ensure that all files, including the new empty ones
241 # will be marked with proper data. 244 # are marked as touched. Content is loaded on demand.
242 # TODO: load file data when necessary 245 touched_files[f] = 1
243 files_data[f] = ''
244 if f in parentctx:
245 files_data[f] = parentctx[f].data()
246 if d2.strip() and len(re.findall('\n[-+]', d2.strip())) > 0: 246 if d2.strip() and len(re.findall('\n[-+]', d2.strip())) > 0:
247 try: 247 try:
248 oldpatchfile = patch.patchfile 248 oldpatchfile = patch.patchfile
249 patch.patchfile = mempatchproxy(parentctx, files_data) 249 patch.patchfile = mempatchproxy(parentctx, files_data)
250 try: 250 try:
264 for x in files_data.iterkeys(): 264 for x in files_data.iterkeys():
265 ui.status('M %s\n' % x) 265 ui.status('M %s\n' % x)
266 # if this patch didn't apply right, fall back to exporting the 266 # if this patch didn't apply right, fall back to exporting the
267 # entire rev. 267 # entire rev.
268 if patch_st == -1: 268 if patch_st == -1:
269 for fn in files_data:
270 if 'l' in parentctx.flags(fn):
271 # I think this might be an underlying bug in svn -
272 # I get diffs of deleted symlinks even though I
273 # specifically said no deletes above.
274 raise BadPatchApply('deleted symlinked prevent patching')
275 assert False, ('This should only happen on case-insensitive' 269 assert False, ('This should only happen on case-insensitive'
276 ' volumes.') 270 ' volumes.')
277 elif patch_st == 1: 271 elif patch_st == 1:
278 # When converting Django, I saw fuzz on .po files that was 272 # When converting Django, I saw fuzz on .po files that was
279 # causing revisions to end up failing verification. If that 273 # causing revisions to end up failing verification. If that
287 for m in property_exec_removed_re.findall(d): 281 for m in property_exec_removed_re.findall(d):
288 exec_files[m] = False 282 exec_files[m] = False
289 for m in property_exec_set_re.findall(d): 283 for m in property_exec_set_re.findall(d):
290 exec_files[m] = True 284 exec_files[m] = True
291 for m in exec_files: 285 for m in exec_files:
292 if m in files_data: 286 touched_files[m] = 1
293 continue
294 data = ''
295 if m in parentctx:
296 data = parentctx[m].data()
297 files_data[m] = data
298 link_files = {} 287 link_files = {}
299 for m in property_special_set_re.findall(d): 288 for m in property_special_set_re.findall(d):
300 # TODO(augie) when a symlink is removed, patching will fail. 289 # TODO(augie) when a symlink is removed, patching will fail.
301 # We're seeing that above - there's gotta be a better 290 # We're seeing that above - there's gotta be a better
302 # workaround than just bailing like that. 291 # workaround than just bailing like that.
303 assert m in files_data 292 assert m in files_data
304 files_data[m] = files_data[m][len('link '):]
305 link_files[m] = True 293 link_files[m] = True
294 for m in property_special_removed_re.findall(d):
295 assert m in files_data
296 link_files[m] = False
306 297
307 for p in r.paths: 298 for p in r.paths:
308 if p.startswith(diff_path) and r.paths[p].action == 'D': 299 if p.startswith(diff_path) and r.paths[p].action == 'D':
309 p2 = p[len(diff_path)+1:].strip('/') 300 p2 = p[len(diff_path)+1:].strip('/')
310 if p2 in parentctx: 301 if p2 in parentctx:
311 files_data[p2] = None 302 files_data[p2] = None
312 continue 303 continue
313 # If this isn't in the parent ctx, it must've been a dir 304 # If this isn't in the parent ctx, it must've been a dir
314 files_data.update([(f, None) for f in parentctx if f.startswith(p2 + '/')]) 305 files_data.update([(f, None) for f in parentctx if f.startswith(p2 + '/')])
315 306
316 copies = getcopies(svn, hg_editor, branch, diff_path, r, files_data, 307 for f in files_data:
308 touched_files[f] = 1
309
310 copies = getcopies(svn, hg_editor, branch, diff_path, r, touched_files,
317 parentctx) 311 parentctx)
318 312
319 def filectxfn(repo, memctx, path): 313 def filectxfn(repo, memctx, path):
320 data = files_data[path] 314 if path in files_data and files_data[path] is None:
321 if data is None:
322 raise IOError() 315 raise IOError()
323 if path not in binary_files: 316
324 isexe = exec_files.get(path, 'x' in parentctx.flags(path)) 317 if path in binary_files:
325 islink = path in link_files
326 else:
327 data, mode = svn.get_file(diff_path + '/' + path, r.revnum) 318 data, mode = svn.get_file(diff_path + '/' + path, r.revnum)
328 isexe = 'x' in mode 319 isexe = 'x' in mode
329 islink = 'l' in mode 320 islink = 'l' in mode
321 else:
322 isexe = exec_files.get(path, 'x' in parentctx.flags(path))
323 islink = link_files.get(path, 'l' in parentctx.flags(path))
324 data = ''
325 if path in files_data:
326 data = files_data[path]
327 if islink:
328 data = data[len('link '):]
329 elif path in parentctx:
330 data = parentctx[path].data()
331
330 copied = copies.get(path) 332 copied = copies.get(path)
331 return context.memfilectx(path=path, data=data, islink=islink, 333 return context.memfilectx(path=path, data=data, islink=islink,
332 isexec=isexe, copied=copied) 334 isexec=isexe, copied=copied)
333 335
334 return list(files_data), filectxfn 336 return list(touched_files), filectxfn
335 337
336 def makecopyfinder(r, branchpath, rootdir): 338 def makecopyfinder(r, branchpath, rootdir):
337 """Return a function detecting copies. 339 """Return a function detecting copies.
338 340
339 Returned copyfinder(path) returns None if no copy information can 341 Returned copyfinder(path) returns None if no copy information can