git-apply: pick up default filenames from "diff --git" header line
Pure mode changes, and deletes or creates of empty files won't have this information anywhere else.maint
parent
fab2c257be
commit
5041aa7040
82
apply.c
82
apply.c
|
@ -36,7 +36,6 @@ static int max_change, max_len;
|
||||||
* things are flags, where -1 means "don't know yet".
|
* things are flags, where -1 means "don't know yet".
|
||||||
*/
|
*/
|
||||||
static int linenr = 1;
|
static int linenr = 1;
|
||||||
static char *def_name = NULL;
|
|
||||||
|
|
||||||
struct fragment {
|
struct fragment {
|
||||||
unsigned long oldpos, oldlines;
|
unsigned long oldpos, oldlines;
|
||||||
|
@ -47,7 +46,7 @@ struct fragment {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct patch {
|
struct patch {
|
||||||
char *new_name, *old_name;
|
char *new_name, *old_name, *def_name;
|
||||||
unsigned int old_mode, new_mode;
|
unsigned int old_mode, new_mode;
|
||||||
int is_rename, is_copy, is_new, is_delete;
|
int is_rename, is_copy, is_new, is_delete;
|
||||||
int lines_added, lines_deleted;
|
int lines_added, lines_deleted;
|
||||||
|
@ -193,15 +192,15 @@ static void parse_traditional_patch(const char *first, const char *second, struc
|
||||||
if (is_dev_null(first)) {
|
if (is_dev_null(first)) {
|
||||||
patch->is_new = 1;
|
patch->is_new = 1;
|
||||||
patch->is_delete = 0;
|
patch->is_delete = 0;
|
||||||
name = find_name(second, def_name, p_value, TERM_SPACE | TERM_TAB);
|
name = find_name(second, NULL, p_value, TERM_SPACE | TERM_TAB);
|
||||||
patch->new_name = name;
|
patch->new_name = name;
|
||||||
} else if (is_dev_null(second)) {
|
} else if (is_dev_null(second)) {
|
||||||
patch->is_new = 0;
|
patch->is_new = 0;
|
||||||
patch->is_delete = 1;
|
patch->is_delete = 1;
|
||||||
name = find_name(first, def_name, p_value, TERM_EXIST | TERM_SPACE | TERM_TAB);
|
name = find_name(first, NULL, p_value, TERM_EXIST | TERM_SPACE | TERM_TAB);
|
||||||
patch->old_name = name;
|
patch->old_name = name;
|
||||||
} else {
|
} else {
|
||||||
name = find_name(first, def_name, p_value, TERM_EXIST | TERM_SPACE | TERM_TAB);
|
name = find_name(first, NULL, p_value, TERM_EXIST | TERM_SPACE | TERM_TAB);
|
||||||
name = find_name(second, name, p_value, TERM_EXIST | TERM_SPACE | TERM_TAB);
|
name = find_name(second, name, p_value, TERM_EXIST | TERM_SPACE | TERM_TAB);
|
||||||
patch->old_name = patch->new_name = name;
|
patch->old_name = patch->new_name = name;
|
||||||
}
|
}
|
||||||
|
@ -285,12 +284,14 @@ static int gitdiff_newmode(const char *line, struct patch *patch)
|
||||||
static int gitdiff_delete(const char *line, struct patch *patch)
|
static int gitdiff_delete(const char *line, struct patch *patch)
|
||||||
{
|
{
|
||||||
patch->is_delete = 1;
|
patch->is_delete = 1;
|
||||||
|
patch->old_name = patch->def_name;
|
||||||
return gitdiff_oldmode(line, patch);
|
return gitdiff_oldmode(line, patch);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int gitdiff_newfile(const char *line, struct patch *patch)
|
static int gitdiff_newfile(const char *line, struct patch *patch)
|
||||||
{
|
{
|
||||||
patch->is_new = 1;
|
patch->is_new = 1;
|
||||||
|
patch->new_name = patch->def_name;
|
||||||
return gitdiff_newmode(line, patch);
|
return gitdiff_newmode(line, patch);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -336,6 +337,61 @@ static int gitdiff_unrecognized(const char *line, struct patch *patch)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static char *git_header_name(char *line)
|
||||||
|
{
|
||||||
|
int len;
|
||||||
|
char *name, *second;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Find the first '/'
|
||||||
|
*/
|
||||||
|
name = line;
|
||||||
|
for (;;) {
|
||||||
|
char c = *name++;
|
||||||
|
if (c == '\n')
|
||||||
|
return NULL;
|
||||||
|
if (c == '/')
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We don't accept absolute paths (/dev/null) as possibly valid
|
||||||
|
*/
|
||||||
|
if (name == line+1)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Accept a name only if it shows up twice, exactly the same
|
||||||
|
* form.
|
||||||
|
*/
|
||||||
|
for (len = 0 ; ; len++) {
|
||||||
|
char c = name[len];
|
||||||
|
|
||||||
|
switch (c) {
|
||||||
|
default:
|
||||||
|
continue;
|
||||||
|
case '\n':
|
||||||
|
break;
|
||||||
|
case '\t': case ' ':
|
||||||
|
second = name+len;
|
||||||
|
for (;;) {
|
||||||
|
char c = *second++;
|
||||||
|
if (c == '\n')
|
||||||
|
return NULL;
|
||||||
|
if (c == '/')
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!memcmp(name, second, len)) {
|
||||||
|
char *ret = xmalloc(len + 1);
|
||||||
|
memcpy(ret, name, len);
|
||||||
|
ret[len] = 0;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/* Verify that we recognize the lines following a git header */
|
/* Verify that we recognize the lines following a git header */
|
||||||
static int parse_git_header(char *line, int len, unsigned int size, struct patch *patch)
|
static int parse_git_header(char *line, int len, unsigned int size, struct patch *patch)
|
||||||
{
|
{
|
||||||
|
@ -345,6 +401,14 @@ static int parse_git_header(char *line, int len, unsigned int size, struct patch
|
||||||
patch->is_new = 0;
|
patch->is_new = 0;
|
||||||
patch->is_delete = 0;
|
patch->is_delete = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Some things may not have the old name in the
|
||||||
|
* rest of the headers anywhere (pure mode changes,
|
||||||
|
* or removing or adding empty files), so we get
|
||||||
|
* the default name from the header.
|
||||||
|
*/
|
||||||
|
patch->def_name = git_header_name(line + strlen("diff --git "));
|
||||||
|
|
||||||
line += len;
|
line += len;
|
||||||
size -= len;
|
size -= len;
|
||||||
linenr++;
|
linenr++;
|
||||||
|
@ -494,7 +558,8 @@ static int find_header(char *line, unsigned long size, int *hdrsize, struct patc
|
||||||
int git_hdr_len = parse_git_header(line, len, size, patch);
|
int git_hdr_len = parse_git_header(line, len, size, patch);
|
||||||
if (git_hdr_len < 0)
|
if (git_hdr_len < 0)
|
||||||
continue;
|
continue;
|
||||||
|
if (!patch->old_name && !patch->new_name)
|
||||||
|
die("git diff header lacks filename information");
|
||||||
*hdrsize = git_hdr_len;
|
*hdrsize = git_hdr_len;
|
||||||
return offset;
|
return offset;
|
||||||
}
|
}
|
||||||
|
@ -630,11 +695,8 @@ static void show_stats(struct patch *patch)
|
||||||
char *name = patch->old_name;
|
char *name = patch->old_name;
|
||||||
int len, max, add, del;
|
int len, max, add, del;
|
||||||
|
|
||||||
if (!name) {
|
if (!name)
|
||||||
name = patch->new_name;
|
name = patch->new_name;
|
||||||
if (!name)
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* "scale" the filename
|
* "scale" the filename
|
||||||
|
|
Loading…
Reference in New Issue