/*
* apply.c
*
* Copyright (C) Linus Torvalds, 2005
*
* This applies patches on top of some (arbitrary) version of the SCM.
*
* NOTE! It does all its work in the index file, and only cares about
* the files in the working directory if you tell it to "merge" the
* patch apply.
*
* Even when merging it always takes the source from the index, and
* uses the working tree as a "branch" for a 3-way merge.
*/
#include <ctype.h>
#include "cache.h"
// We default to the merge behaviour, since that's what most people would
// expect.
//
// --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
// --show-files shows the directory changes
//
static int merge_patch = 1;
static int check_index = 0;
static int write_index = 0;
static int diffstat = 0;
static int summary = 0;
static int check = 0;
static int apply = 1;
static int show_files = 0;
static const char apply_usage[] = "git-apply [--stat] [--summary] [--check] [--show-files] <patch>";
/*
* For "diff-stat" like behaviour, we keep track of the biggest change
* we've seen, and the longest filename. That allows us to do simple
* scaling.
*/
static int max_change, max_len;
/*
* Various "current state", notably line numbers and what
* file (and how) we're patching right now.. The "is_xxxx"
* things are flags, where -1 means "don't know yet".
*/
static int linenr = 1;
struct fragment {
unsigned long oldpos, oldlines;
unsigned long newpos, newlines;
const char *patch;
int size;
struct fragment *next;
};
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 lines_added, lines_deleted;
int score;
struct fragment *fragments;
char *result;
unsigned long resultsize;
struct patch *next;
};
#define CHUNKSIZE (8192)
#define SLOP (16)
static void *read_patch_file(int fd, unsigned long *sizep)
{
unsigned long size = 0, alloc = CHUNKSIZE;
void *buffer = xmalloc(alloc);
for (;;) {
int nr = alloc - size;
if (nr < 1024) {
alloc += CHUNKSIZE;
buffer = xrealloc(buffer, alloc);
nr = alloc - size;
}
nr = read(fd, buffer + size, nr);
if (!nr)
break;
if (nr < 0) {
|