Mercurial > hgsubversion
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 |
