Thread (1 message) 1 message, 1 author, 2016-06-15
DORMANTno replies

[PATCH 2/4] apply: allow-binary-replacement.

From: Junio C Hamano <hidden>
Date: 2016-06-15 22:42:12
Subsystem: documentation, the rest · Maintainers: Jonathan Corbet, Linus Torvalds

A new option, --allow-binary-replacement, is introduced.

When you feed a diff that records full SHA1 name of pre- and
post-image blob on its index line to git-apply with this option,
the post-image blob replaces the path if what you have in the
working tree matches the pre-image _and_ post-image blob is
already available in the object directory.

Later we _might_ want to enhance the diff output to also include
the full binary data of the post-image, to make this more
useful, but this is good enough for local rebasing application.

Signed-off-by: Junio C Hamano <redacted>

---

 Documentation/git-apply.txt |   13 +++++++-
 apply.c                     |   72 +++++++++++++++++++++++++++++++++++++++++--
 2 files changed, 81 insertions(+), 4 deletions(-)

applies-to: 4567363448244862ec2c6c8bd74fc09cd322f153
0d534967c6850288e1a36eae364da700348a77fe
diff --git a/Documentation/git-apply.txt b/Documentation/git-apply.txt
index 6702a18..626e281 100644
--- a/Documentation/git-apply.txt
+++ b/Documentation/git-apply.txt
@@ -8,7 +8,7 @@ git-apply - Apply patch on a git index f
 
 SYNOPSIS
 --------
-'git-apply' [--stat] [--numstat] [--summary] [--check] [--index] [--apply] [--no-add] [--index-info] [-z] [<patch>...]
+'git-apply' [--stat] [--numstat] [--summary] [--check] [--index] [--apply] [--no-add] [--index-info] [--allow-binary-replacement] [-z] [<patch>...]
 
 DESCRIPTION
 -----------
@@ -79,6 +79,17 @@ OPTIONS
 	the result with this option, which would apply the
 	deletion part but not addition part.
 
+--allow-binary-replacement::
+	When applying a patch, which is a git-enhanced patch
+	that was prepared to record the pre- and post-image object
+	name in full, and the path being patched exactly matches
+	the object the patch applies to (i.e. "index" line's
+	pre-image object name is what is in the working tree),
+	and the post-image object is available in the object
+	database, use the post-image object as the patch
+	result.  This allows binary files to be patched in a
+	very limited way.
+
 Author
 ------
 Written by Linus Torvalds <torvalds@osdl.org>
diff --git a/apply.c b/apply.c
index 590adc6..cb9a6c0 100644
--- a/apply.c
+++ b/apply.c
@@ -16,6 +16,7 @@
 //  --numstat does numeric diffstat, and doesn't actually apply
 //  --index-info shows the old and new index info for paths if available.
 //
+static int allow_binary_replacement = 0;
 static int check_index = 0;
 static int write_index = 0;
 static int diffstat = 0;
@@ -27,7 +28,7 @@ static int no_add = 0;
 static int show_index_info = 0;
 static int line_termination = '\n';
 static const char apply_usage[] =
-"git-apply [--stat] [--numstat] [--summary] [--check] [--index] [--apply] [--no-add] [--index-info] [-z] <patch>...";
+"git-apply [--stat] [--numstat] [--summary] [--check] [--index] [--apply] [--no-add] [--index-info] [--allow-binary-replacement] [-z] <patch>...";
 
 /*
  * For "diff-stat" like behaviour, we keep track of the biggest change
@@ -899,8 +900,12 @@ static int parse_chunk(char *buffer, uns
 			    sizeof(binhdr)-1))
 			patch->is_binary = 1;
 
-		if (patch->is_binary && !apply && !check)
-			;
+		if (patch->is_binary) {
+			if ((!apply && !check) || allow_binary_replacement)
+				;
+			else
+				die("binary patch at line %d; you might want to try --allow-binary-replacement?", linenr);
+		}
 		else
 			die("patch with only garbage at line %d", linenr);
 	}
@@ -1156,6 +1161,63 @@ static int apply_fragments(struct buffer
 {
 	struct fragment *frag = patch->fragments;
 
+	if (patch->is_binary) {
+		unsigned char sha1[20];
+		const char *name = patch->old_name ? patch->old_name : patch->new_name;
+
+		if (!allow_binary_replacement)
+			return error("cannot apply binary patch to '%s' without --allow-binary-replacement", name);
+
+		/* For safety, we require patch index line to contain
+		 * full 40-byte textual SHA1 for old and new, at least for now.
+		 */
+		if (strlen(patch->old_sha1_prefix) != 40 ||
+		    strlen(patch->new_sha1_prefix) != 40 ||
+		    get_sha1_hex(patch->old_sha1_prefix, sha1) ||
+		    get_sha1_hex(patch->new_sha1_prefix, sha1))
+			return error("cannot apply binary patch to '%s' without full index line", name);
+
+		if (patch->old_name) {
+			unsigned char hdr[50];
+			int hdrlen;
+
+			/* See if the old one matches what the patch
+			 * applies to.
+			 */
+			write_sha1_file_prepare(desc->buffer, desc->size,
+						"blob", sha1, hdr, &hdrlen);
+			if (strcmp(sha1_to_hex(sha1), patch->old_sha1_prefix))
+				return error("the patch applies to '%s' (%s), which does not match the current contents.", name, sha1_to_hex(sha1));
+		}
+		else {
+			/* Otherwise, the old one must be empty. */
+			if (desc->size)
+				return error("the patch applies to an empty '%s' but it is not empty", name);
+		}
+
+		/* For now, we do not record post-image data in the patch,
+		 * and require the object already present in the recipient's
+		 * object database.
+		 */
+		if (desc->buffer) {
+			free(desc->buffer);
+			desc->alloc = desc->size = 0;
+		}
+		get_sha1_hex(patch->new_sha1_prefix, sha1);
+
+		if (memcmp(sha1, null_sha1, 20)) {
+			char type[10];
+			unsigned long size;
+
+			desc->buffer = read_sha1_file(sha1, type, &size);
+			if (!desc->buffer)
+				return error("the necessary postimage %s for '%s' does not exist", patch->new_sha1_prefix, name);
+			desc->alloc = desc->size = size;
+		}
+
+		return 0;
+	}
+
 	while (frag) {
 		if (apply_one_fragment(desc, frag) < 0)
 			return error("patch failed: %s:%ld", patch->old_name, frag->oldpos);
@@ -1723,6 +1785,10 @@ int main(int argc, char **argv)
 			diffstat = 1;
 			continue;
 		}
+		if (!strcmp(arg, "--allow-binary-replacement")) {
+			allow_binary_replacement = 1;
+			continue;
+		}
 		if (!strcmp(arg, "--numstat")) {
 			apply = 0;
 			numstat = 1;
---
0.99.9.GIT
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help