Skip to content
Snippets Groups Projects
Commit edce6404 authored by Georges Racinet's avatar Georges Racinet
Browse files

hgitaly.diff.Chunk: adopted and improved the index line insertion function

It is now able to understand diff headers generated without the option
that dumps the full binary content in Git format, and returns whether
a binary placeholder is to be generated.
parent 29a5c901
No related branches found
No related tags found
2 merge requests!232Merged stable branch into default,!228DiffService.GetPatchID and install/config doc
......@@ -7,6 +7,7 @@
"""Utilities for comparison of content between changesets."""
import attr
from functools import cached_property
import re
from mercurial import (
copies,
......@@ -40,6 +41,8 @@
"""Mapping status object attributes to ChangedPaths enum."""
COPIED = ChangedPaths.Status.COPIED
DIFF_HUNKS_START_RX = re.compile(rb'^(--- )|^(Binary file)')
"""To match the header line right before hunks start getting dumped."""
def changed_paths(repo, from_ctx, to_ctx, base_path):
......@@ -230,3 +233,35 @@
adds += add_count
dels += del_count
return adds, dels
def header_with_index_line(self):
"""Generate header with the index line and binary indication.
The index line is the expected Git-style one, with file modes etc.
The binary indication tells whether there should be a placeholder
instead actual Git binary content section. Callers can use it to
generate the appropriate placeholder for their needs.
"""
fname = self.hg_chunk.filename()
old_bid, new_bid = self.from_to_blob_oids()
indexline = ('index %s..%s' % (old_bid, new_bid)).encode('ascii')
# Note: <mode> is required only when it didn't change between
# the two changesets, otherwise it has a separate line
if self.to_filectx is not None and self.to_filectx.path() == fname:
oldmode, mode = self.from_to_file_mode()
if mode == oldmode:
indexline += b' ' + mode
indexline += b'\n'
headerlines = self.hg_chunk.header
binary = False
for index, line in enumerate(headerlines[:]):
m = DIFF_HUNKS_START_RX.match(line)
if m is None:
continue
binary = not bool(m.group(1))
headerlines.insert(index, indexline)
break
return b''.join(headerlines), binary
......@@ -412,6 +412,7 @@
# generator func to yield hunks
def in_chunks():
for chunk in patchmod.parsepatch(diffchunks):
header = _insert_blob_index(chunk, ctx_from, ctx_to)
for hg_chunk in patchmod.parsepatch(diffchunks):
chunk = Chunk(hg_chunk, ctx_from, ctx_to)
header, _bin_placeholder = chunk.header_with_index_line()
yield header
......@@ -417,5 +418,6 @@
yield header
for hunk in chunk.hunks:
for hunk in hg_chunk.hunks:
with BytesIO() as extracted:
hunk.write(extracted)
yield extracted.getvalue()
......@@ -570,29 +572,6 @@
return (True, repo, ctx_from, ctx_to)
def _insert_blob_index(hg_chunk, ctx_from, ctx_to):
fname = hg_chunk.filename()
chunk = Chunk(hg_chunk, ctx_from, ctx_to)
old_bid, new_bid = chunk.from_to_blob_oids()
indexline = 'index %s..%s' % (old_bid, new_bid)
indexline = pycompat.sysbytes(indexline)
# Note: <mode> is required only when it didn't change between
# the two changesets, otherwise it has a separate line
if chunk.to_filectx is not None and chunk.to_filectx.path() == fname:
oldmode, mode = chunk.from_to_file_mode()
if mode == oldmode:
indexline += b' ' + mode
indexline += b'\n'
headerlines = hg_chunk.header
for index, line in enumerate(headerlines[:]):
if line.startswith(b'--- '):
headerlines.insert(index, indexline)
break
return b''.join(headerlines)
def _exportsingle(repo, ctx, fm, seqno, diffopts):
"""Generator method which yields a bytes stream of exporting `ctx` data.
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment