summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: 4dfdbe1)
raw | patch | inline | side by side (parent: 4dfdbe1)
author | Linus Torvalds <torvalds@ppc970.osdl.org> | |
Tue, 24 May 2005 02:13:55 +0000 (19:13 -0700) | ||
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | |
Tue, 24 May 2005 02:13:55 +0000 (19:13 -0700) |
Right now we only use it to figure out what the filename might
be when that is ambiguous, but we'll get there..
be when that is ambiguous, but we'll get there..
apply.c | patch | blob | history |
index f3b686541c568004c7e19edd9e30f313a224c7e7..9dba588f028d36502e92aaba2785029a4be5be43 100644 (file)
--- a/apply.c
+++ b/apply.c
return !memcmp("/dev/null", str, 9) && isspace(str[9]);
}
-static char * find_name(const char *line, char *def, int p_value)
+#define TERM_EXIST 1
+#define TERM_SPACE 2
+#define TERM_TAB 4
+
+static int name_terminate(const char *name, int namelen, int c, int terminate)
+{
+ if (c == ' ' && !(terminate & TERM_SPACE))
+ return 0;
+ if (c == '\t' && !(terminate & TERM_TAB))
+ return 0;
+
+ /*
+ * Do we want an existing name? Return false and
+ * continue if it's not there.
+ */
+ if (terminate & TERM_EXIST)
+ return cache_name_pos(name, namelen) >= 0;
+
+ return 1;
+}
+
+static char * find_name(const char *line, char *def, int p_value, int terminate)
{
int len;
const char *start = line;
for (;;) {
char c = *line;
- if (isspace(c))
- break;
+
+ if (isspace(c)) {
+ if (c == '\n')
+ break;
+ if (name_terminate(start, line-start, c, terminate))
+ break;
+ }
line++;
if (c == '/' && !--p_value)
start = line;
* Get the name etc info from the --/+++ lines of a traditional patch header
*
* NOTE! This hardcodes "-p1" behaviour in filename detection.
+ *
+ * FIXME! The end-of-filename heuristics are kind of screwy. For existing
+ * files, we can happily check the index for a match, but for creating a
+ * new file we should try to match whatever "patch" does. I have no idea.
*/
static int parse_traditional_patch(const char *first, const char *second)
{
second += 4; // skip "+++ "
if (is_dev_null(first)) {
is_new = 1;
- name = find_name(second, def_name, p_value);
+ name = find_name(second, def_name, p_value, TERM_SPACE | TERM_TAB);
+ new_name = name;
} else if (is_dev_null(second)) {
is_delete = 1;
- name = find_name(first, def_name, p_value);
+ name = find_name(first, def_name, p_value, TERM_EXIST | TERM_SPACE | TERM_TAB);
+ old_name = name;
} else {
- name = find_name(first, def_name, p_value);
- name = find_name(second, name, p_value);
+ name = find_name(first, def_name, p_value, TERM_EXIST | TERM_SPACE | TERM_TAB);
+ name = find_name(second, name, p_value, TERM_EXIST | TERM_SPACE | TERM_TAB);
+ old_name = new_name = name;
}
if (!name)
die("unable to find filename in patch at line %d", linenr);
- old_name = name;
- new_name = name;
}
static int gitdiff_hdrend(const char *line)
static int gitdiff_oldname(const char *line)
{
- if (!old_name)
- old_name = find_name(line, NULL, 1);
+ if (!old_name && !is_new)
+ old_name = find_name(line, NULL, 1, 0);
return 0;
}
static int gitdiff_newname(const char *line)
{
- if (!new_name)
- new_name = find_name(line, NULL, 1);
+ if (!new_name && !is_delete)
+ new_name = find_name(line, NULL, 1, 0);
return 0;
}
static int gitdiff_copysrc(const char *line)
{
is_copy = 1;
- old_name = find_name(line, NULL, 0);
+ old_name = find_name(line, NULL, 0, 0);
return 0;
}
static int gitdiff_copydst(const char *line)
{
is_copy = 1;
- new_name = find_name(line, NULL, 0);
+ new_name = find_name(line, NULL, 0, 0);
return 0;
}
static int gitdiff_renamesrc(const char *line)
{
is_rename = 1;
- old_name = find_name(line, NULL, 0);
+ old_name = find_name(line, NULL, 0, 0);
return 0;
}
static int gitdiff_renamedst(const char *line)
{
is_rename = 1;
- new_name = find_name(line, NULL, 0);
+ new_name = find_name(line, NULL, 0, 0);
return 0;
}
return 0;
}
+/*
+ * This is normal for a diff that doesn't change anything: we'll fall through
+ * into the next diff. Tell the parser to break out.
+ */
+static int gitdiff_unrecognized(const char *line)
+{
+ return -1;
+}
+
/* Verify that we recognize the lines following a git header */
static int parse_git_header(char *line, int len, unsigned int size)
{
{ "rename from ", gitdiff_renamesrc },
{ "rename to ", gitdiff_renamedst },
{ "similarity index ", gitdiff_similarity },
+ { "", gitdiff_unrecognized },
};
int i;
continue;
if (p->fn(line + oplen) < 0)
return offset;
+ break;
}
}
printf("Copy: %d\n", is_copy);
printf("New: %d\n", is_new);
printf("Delete: %d\n", is_delete);
-printf("Mode: %o->%o\n", old_mode, new_mode);
-printf("Name: '%s'->'%s'\n", old_name, new_name);
+printf("Mode: %o:%o\n", old_mode, new_mode);
+printf("Name: '%s':'%s'\n", old_name, new_name);
+
+ if (old_name && cache_name_pos(old_name, strlen(old_name)) < 0)
+ die("file %s does not exist", old_name);
+ if (new_name && (is_new | is_rename | is_copy)) {
+ if (cache_name_pos(new_name, strlen(new_name)) >= 0)
+ die("file %s already exists", new_name);
+ }
patch = header + hdrsize;
patchsize = apply_single_patch(patch, size - offset - hdrsize);