15
15
# along with this program; if not, write to the Free Software
16
16
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18
from __future__ import absolute_import
20
18
from .errors import (
419
418
for line in iter_lines:
420
419
if line.startswith(b'=== '):
421
if len(saved_lines) > 0:
420
if allow_dirty and beginning:
421
# Patches can have "junk" at the beginning
422
# Stripping junk from the end of patches is handled when we
425
elif len(saved_lines) > 0:
422
426
if keep_dirty and len(dirty_head) > 0:
423
427
yield {'saved_lines': saved_lines,
424
428
'dirty_head': dirty_head}
546
550
for hunk_line in hunk.lines:
547
seen_patch.append(str(hunk_line))
551
seen_patch.append(hunk_line.contents)
548
552
if isinstance(hunk_line, InsertLine):
549
553
yield hunk_line.contents
550
554
elif isinstance(hunk_line, (ContextLine, RemoveLine)):
551
555
orig_line = next(orig_lines)
552
556
if orig_line != hunk_line.contents:
553
557
raise PatchConflict(line_no, orig_line,
554
b"".join(seen_patch))
558
b''.join(seen_patch))
555
559
if isinstance(hunk_line, ContextLine):
561
565
if orig_lines is not None:
562
566
for line in orig_lines:
570
def apply_patches(tt, patches, prefix=1):
571
"""Apply patches to a TreeTransform.
573
:param tt: TreeTransform instance
574
:param patches: List of patches
575
:param prefix: Number leading path segments to strip
578
return '/'.join(p.split('/')[1:])
580
from breezy.bzr.generate_ids import gen_file_id
581
# TODO(jelmer): Extract and set mode
582
for patch in patches:
583
if patch.oldname == b'/dev/null':
587
oldname = strip_prefix(patch.oldname.decode())
588
trans_id = tt.trans_id_tree_path(oldname)
589
orig_contents = tt._tree.get_file_text(oldname)
590
tt.delete_contents(trans_id)
592
if patch.newname != b'/dev/null':
593
newname = strip_prefix(patch.newname.decode())
594
new_contents = iter_patched_from_hunks(
595
orig_contents.splitlines(True), patch.hunks)
597
parts = os.path.split(newname)
599
for part in parts[1:-1]:
600
trans_id = tt.new_directory(part, trans_id)
602
parts[-1], trans_id, new_contents,
603
file_id=gen_file_id(newname))
605
tt.create_file(new_contents, trans_id)
608
class AppliedPatches(object):
609
"""Context that provides access to a tree with patches applied.
612
def __init__(self, tree, patches, prefix=1):
614
self.patches = patches
618
self._tt = self.tree.preview_transform()
619
apply_patches(self._tt, self.patches, prefix=self.prefix)
620
return self._tt.get_preview_tree()
622
def __exit__(self, exc_type, exc_value, exc_tb):