specfile cleanups
[gitweb.git] / apply.c
diff --git a/apply.c b/apply.c
index e5c0b7d074936507159353cb5699d17897c8b1e4..cf8aa87a289bfa534405c461323eae5452c96d1e 100644 (file)
--- a/apply.c
+++ b/apply.c
 //  --check turns on checking that the working tree matches the
 //    files that are being modified, but doesn't apply the patch
 //  --stat does just a diffstat, and doesn't actually apply
+//  --numstat does numeric diffstat, and doesn't actually apply
 //  --index-info shows the old and new index info for paths if available.
 //
 static int check_index = 0;
 static int write_index = 0;
 static int diffstat = 0;
+static int numstat = 0;
 static int summary = 0;
 static int check = 0;
 static int apply = 1;
 static int show_index_info = 0;
 static int line_termination = '\n';
 static const char apply_usage[] =
-"git-apply [--stat] [--summary] [--check] [--index] [--apply] [--index-info] [-z] <patch>...";
+"git-apply [--stat] [--numstat] [--summary] [--check] [--index] [--apply] [--index-info] [-z] <patch>...";
 
 /*
  * For "diff-stat" like behaviour, we keep track of the biggest change
@@ -51,7 +53,7 @@ struct fragment {
 struct patch {
        char *new_name, *old_name, *def_name;
        unsigned int old_mode, new_mode;
-       int is_rename, is_copy, is_new, is_delete;
+       int is_rename, is_copy, is_new, is_delete, is_binary;
        int lines_added, lines_deleted;
        int score;
        struct fragment *fragments;
@@ -888,8 +890,18 @@ static int parse_chunk(char *buffer, unsigned long size, struct patch *patch)
 
        patchsize = parse_single_patch(buffer + offset + hdrsize, size - offset - hdrsize, patch);
 
-       if (!patchsize && !metadata_changes(patch))
-               die("patch with only garbage at line %d", linenr);
+       if (!patchsize && !metadata_changes(patch)) {
+               static const char binhdr[] = "Binary files ";
+
+               if (sizeof(binhdr) - 1 < size - offset - hdrsize &&
+                   !memcmp(binhdr, buffer + hdrsize, sizeof(binhdr)-1))
+                       patch->is_binary = 1;
+
+               if (patch->is_binary && !apply && !check)
+                       ;
+               else
+                       die("patch with only garbage at line %d", linenr);
+       }
 
        return offset + hdrsize + patchsize;
 }
@@ -947,9 +959,12 @@ static void show_stats(struct patch *patch)
                add = (add * max + max_change / 2) / max_change;
                del = total - add;
        }
-       printf(" %s%-*s |%5d %.*s%.*s\n", prefix,
-               len, name, patch->lines_added + patch->lines_deleted,
-               add, pluses, del, minuses);
+       if (patch->is_binary)
+               printf(" %s%-*s |  Bin\n", prefix, len, name);
+       else
+               printf(" %s%-*s |%5d %.*s%.*s\n", prefix,
+                      len, name, patch->lines_added + patch->lines_deleted,
+                      add, pluses, del, minuses);
        if (qname)
                free(qname);
 }
@@ -1317,6 +1332,20 @@ static void stat_patch_list(struct patch *patch)
        printf(" %d files changed, %d insertions(+), %d deletions(-)\n", files, adds, dels);
 }
 
+static void numstat_patch_list(struct patch *patch)
+{
+       for ( ; patch; patch = patch->next) {
+               const char *name;
+               name = patch->old_name ? patch->old_name : patch->new_name;
+               printf("%d\t%d\t", patch->lines_added, patch->lines_deleted);
+               if (line_termination && quote_c_style(name, NULL, NULL, 0))
+                       quote_c_style(name, NULL, stdout, 0);
+               else
+                       fputs(name, stdout);
+               putchar('\n');
+       }
+}
+
 static void show_file_mode_name(const char *newdelete, unsigned int mode, const char *name)
 {
        if (mode)
@@ -1650,6 +1679,9 @@ static int apply_patch(int fd)
        if (diffstat)
                stat_patch_list(list);
 
+       if (numstat)
+               numstat_patch_list(list);
+
        if (summary)
                summary_patch_list(list);
 
@@ -1683,6 +1715,11 @@ int main(int argc, char **argv)
                        diffstat = 1;
                        continue;
                }
+               if (!strcmp(arg, "--numstat")) {
+                       apply = 0;
+                       numstat = 1;
+                       continue;
+               }
                if (!strcmp(arg, "--summary")) {
                        apply = 0;
                        summary = 1;