*
* 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 <fnmatch.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 apply = 1;
static int show_files = 0;
static const char apply_usage[] =
-"git-apply [--no-merge] [--stat] [--summary] [--check] [--index] [--apply] [--show-files] <patch>...";
+"git-apply [--stat] [--summary] [--check] [--index] [--apply] [--show-files] <patch>...";
/*
* For "diff-stat" like behaviour, we keep track of the biggest change
added++;
newlines--;
break;
- /* We allow "\ No newline at end of file" */
+
+ /* We allow "\ No newline at end of file". Depending
+ * on locale settings when the patch was produced we
+ * don't know what this line looks like. The only
+ * thing we do know is that it begins with "\ ".
+ * Checking for 12 is just for sanity check -- any
+ * l10n of "\ No newline..." is at least that long.
+ */
case '\\':
- if (len < 12 || memcmp(line, "\\ No newline", 12))
+ if (len < 12 || memcmp(line, "\\ ", 2))
return -1;
break;
}
* it in the above loop because we hit oldlines == newlines == 0
* before seeing it.
*/
- if (12 < size && !memcmp(line, "\\ No newline", 12))
+ if (12 < size && !memcmp(line, "\\ ", 2))
offset += linelen(line, size);
patch->lines_added += added;
return offset;
}
+static inline int metadata_changes(struct patch *patch)
+{
+ return patch->is_rename > 0 ||
+ patch->is_copy > 0 ||
+ patch->is_new > 0 ||
+ patch->is_delete ||
+ (patch->old_mode && patch->new_mode &&
+ patch->old_mode != patch->new_mode);
+}
+
static int parse_chunk(char *buffer, unsigned long size, struct patch *patch)
{
int hdrsize, patchsize;
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);
+
return offset + hdrsize + patchsize;
}
if (old_name) {
int changed;
+ int stat_ret = lstat(old_name, &st);
- if (lstat(old_name, &st) < 0)
- return error("%s: %s", old_name, strerror(errno));
if (check_index) {
int pos = cache_name_pos(old_name, strlen(old_name));
if (pos < 0)
- return error("%s: does not exist in index", old_name);
+ return error("%s: does not exist in index",
+ old_name);
+ if (stat_ret < 0) {
+ struct checkout costate;
+ if (errno != ENOENT)
+ return error("%s: %s", old_name,
+ strerror(errno));
+ /* checkout */
+ costate.base_dir = "";
+ costate.base_dir_len = 0;
+ costate.force = 0;
+ costate.quiet = 0;
+ costate.not_new = 0;
+ costate.refresh_cache = 1;
+ if (checkout_entry(active_cache[pos],
+ &costate) ||
+ lstat(old_name, &st))
+ return -1;
+ }
+
changed = ce_match_stat(active_cache[pos], &st);
if (changed)
- return error("%s: does not match index", old_name);
+ return error("%s: does not match index",
+ old_name);
}
+ else if (stat_ret < 0)
+ return error("%s: %s", old_name, strerror(errno));
+
if (patch->is_new < 0)
patch->is_new = 0;
st.st_mode = ntohl(create_ce_mode(st.st_mode));
static int use_patch(struct patch *p)
{
- const char *pathname = p->new_name ? : p->old_name;
+ const char *pathname = p->new_name ? p->new_name : p->old_name;
struct excludes *x = excludes;
while (x) {
if (fnmatch(x->path, pathname, 0) == 0)
excludes = x;
continue;
}
- /* NEEDSWORK: this does not do anything at this moment. */
- if (!strcmp(arg, "--no-merge")) {
- merge_patch = 0;
- continue;
- }
if (!strcmp(arg, "--stat")) {
apply = 0;
diffstat = 1;