Mercurial > public > mercurial-scm > hg-stable
comparison mercurial/patch.py @ 14391:1e64e1e12195
patch: unify backend file access interface
- Rename readlines() into getfile(), return data and mode
- Make setfile() write a data buffer instead of lines, make mode mandatory.
author | Patrick Mezard <pmezard@gmail.com> |
---|---|
date | Thu, 19 May 2011 22:49:43 +0200 |
parents | ce77c275bec3 |
children | bb5cbc16349e |
comparison
equal
deleted
inserted
replaced
14390:ce77c275bec3 | 14391:1e64e1e12195 |
---|---|
364 | 364 |
365 class abstractbackend(object): | 365 class abstractbackend(object): |
366 def __init__(self, ui): | 366 def __init__(self, ui): |
367 self.ui = ui | 367 self.ui = ui |
368 | 368 |
369 def readlines(self, fname): | 369 def getfile(self, fname): |
370 """Return target file lines, or its content as a single line | 370 """Return target file data and flags as a (data, (islink, |
371 for symlinks. | 371 isexec)) tuple. |
372 """ | 372 """ |
373 raise NotImplementedError | 373 raise NotImplementedError |
374 | 374 |
375 def setfile(self, fname, lines, mode): | 375 def setfile(self, fname, data, mode): |
376 """Write lines to target file. mode is a (islink, isexec) | 376 """Write data to target file fname and set its mode. mode is a |
377 tuple, or None if there is no mode information. If lines is None, | 377 (islink, isexec) tuple. If data is None, the file content should |
378 the file must exists and its content is left unchanged. | 378 be left unchanged. |
379 """ | 379 """ |
380 raise NotImplementedError | 380 raise NotImplementedError |
381 | 381 |
382 def unlink(self, fname): | 382 def unlink(self, fname): |
383 """Unlink target file.""" | 383 """Unlink target file.""" |
406 self.opener = scmutil.opener(basedir) | 406 self.opener = scmutil.opener(basedir) |
407 | 407 |
408 def _join(self, f): | 408 def _join(self, f): |
409 return os.path.join(self.opener.base, f) | 409 return os.path.join(self.opener.base, f) |
410 | 410 |
411 def readlines(self, fname): | 411 def getfile(self, fname): |
412 if os.path.islink(self._join(fname)): | 412 path = self._join(fname) |
413 return [os.readlink(self._join(fname))] | 413 if os.path.islink(path): |
414 fp = self.opener(fname, 'r') | 414 return (os.readlink(path), (True, False)) |
415 isexec, islink = False, False | |
415 try: | 416 try: |
416 return list(fp) | 417 isexec = os.lstat(path).st_mode & 0100 != 0 |
417 finally: | 418 islink = os.path.islink(path) |
418 fp.close() | 419 except OSError, e: |
419 | 420 if e.errno != errno.ENOENT: |
420 def setfile(self, fname, lines, mode): | 421 raise |
421 if lines is None: | 422 return (self.opener.read(fname), (islink, isexec)) |
422 if mode: | 423 |
423 util.setflags(self._join(fname), mode[0], mode[1]) | 424 def setfile(self, fname, data, mode): |
425 islink, isexec = mode | |
426 if data is None: | |
427 util.setflags(self._join(fname), islink, isexec) | |
424 return | 428 return |
425 if not mode: | 429 if islink: |
426 # Preserve mode information | 430 self.opener.symlink(data, fname) |
427 isexec, islink = False, False | |
428 try: | |
429 isexec = os.lstat(self._join(fname)).st_mode & 0100 != 0 | |
430 islink = os.path.islink(self._join(fname)) | |
431 except OSError, e: | |
432 if e.errno != errno.ENOENT: | |
433 raise | |
434 else: | 431 else: |
435 islink, isexec = mode | 432 self.opener.write(fname, data) |
436 if islink: | |
437 self.opener.symlink(''.join(lines), fname) | |
438 else: | |
439 self.opener(fname, 'w').writelines(lines) | |
440 if isexec: | 433 if isexec: |
441 util.setflags(self._join(fname), False, True) | 434 util.setflags(self._join(fname), False, True) |
442 | 435 |
443 def unlink(self, fname): | 436 def unlink(self, fname): |
444 try: | 437 try: |
483 self.similarity = similarity | 476 self.similarity = similarity |
484 self.removed = set() | 477 self.removed = set() |
485 self.changed = set() | 478 self.changed = set() |
486 self.copied = [] | 479 self.copied = [] |
487 | 480 |
488 def setfile(self, fname, lines, mode): | 481 def setfile(self, fname, data, mode): |
489 super(workingbackend, self).setfile(fname, lines, mode) | 482 super(workingbackend, self).setfile(fname, data, mode) |
490 self.changed.add(fname) | 483 self.changed.add(fname) |
491 | 484 |
492 def unlink(self, fname): | 485 def unlink(self, fname): |
493 super(workingbackend, self).unlink(fname) | 486 super(workingbackend, self).unlink(fname) |
494 self.removed.add(fname) | 487 self.removed.add(fname) |
532 self.exists = False | 525 self.exists = False |
533 self.missing = missing | 526 self.missing = missing |
534 self.mode = mode | 527 self.mode = mode |
535 if not missing: | 528 if not missing: |
536 try: | 529 try: |
537 self.lines = self.backend.readlines(fname) | 530 data, mode = self.backend.getfile(fname) |
531 if data: | |
532 self.lines = data.splitlines(True) | |
533 if self.mode is None: | |
534 self.mode = mode | |
538 if self.lines: | 535 if self.lines: |
539 # Normalize line endings | 536 # Normalize line endings |
540 if self.lines[0].endswith('\r\n'): | 537 if self.lines[0].endswith('\r\n'): |
541 self.eol = '\r\n' | 538 self.eol = '\r\n' |
542 elif self.lines[0].endswith('\n'): | 539 elif self.lines[0].endswith('\n'): |
548 l = l[:-2] + '\n' | 545 l = l[:-2] + '\n' |
549 nlines.append(l) | 546 nlines.append(l) |
550 self.lines = nlines | 547 self.lines = nlines |
551 self.exists = True | 548 self.exists = True |
552 except IOError: | 549 except IOError: |
553 pass | 550 if self.mode is None: |
551 self.mode = (False, False) | |
554 else: | 552 else: |
555 self.ui.warn(_("unable to find '%s' for patching\n") % self.fname) | 553 self.ui.warn(_("unable to find '%s' for patching\n") % self.fname) |
556 | 554 |
557 self.hash = {} | 555 self.hash = {} |
558 self.dirty = 0 | 556 self.dirty = 0 |
577 if l and l[-1] == '\n': | 575 if l and l[-1] == '\n': |
578 l = l[:-1] + eol | 576 l = l[:-1] + eol |
579 rawlines.append(l) | 577 rawlines.append(l) |
580 lines = rawlines | 578 lines = rawlines |
581 | 579 |
582 self.backend.setfile(fname, lines, mode) | 580 self.backend.setfile(fname, ''.join(lines), mode) |
583 | 581 |
584 def printfile(self, warn): | 582 def printfile(self, warn): |
585 if self.fileprinted: | 583 if self.fileprinted: |
586 return | 584 return |
587 if warn or self.ui.verbose: | 585 if warn or self.ui.verbose: |
1248 if gp.mode and not first_hunk: | 1246 if gp.mode and not first_hunk: |
1249 data = None | 1247 data = None |
1250 if gp.op == 'ADD': | 1248 if gp.op == 'ADD': |
1251 # Added files without content have no hunk and | 1249 # Added files without content have no hunk and |
1252 # must be created | 1250 # must be created |
1253 data = [] | 1251 data = '' |
1254 backend.setfile(path, data, gp.mode) | 1252 backend.setfile(path, data, gp.mode) |
1255 if not first_hunk: | 1253 if not first_hunk: |
1256 continue | 1254 continue |
1257 try: | 1255 try: |
1258 mode = gp and gp.mode or None | 1256 mode = gp and gp.mode or None |