diff options
author | Andreas Gruenbacher <agruen@suse.de> | 2010-04-29 15:09:36 +0200 |
---|---|---|
committer | Andreas Gruenbacher <agruen@suse.de> | 2010-05-02 11:44:03 +0200 |
commit | 5f3b6a06a14899717ecefbbf8f20975fa4875e71 (patch) | |
tree | e36daf83a73d1b1163624954d19f901692d2f96f | |
parent | b68294e3e1177bcf98d6d23f90ef3e6b5576af2a (diff) | |
download | patch-5f3b6a06a14899717ecefbbf8f20975fa4875e71.tar.gz |
git diffs: Parse copy and rename headers
* src/pch.c (p_copy, p_rename): New variables.
(pch_copy, pch_rename): New functions.
(intuit_diff_type): Parse the "copy from", "copy to", "rename from",
and "rename to" headers.
* src/util.c (fetchname): Return the fetched name per reference (after
freeing the previous name if any). Also free the previous timestamp
string if any.
-rw-r--r-- | ChangeLog | 8 | ||||
-rw-r--r-- | src/pch.c | 77 | ||||
-rw-r--r-- | src/pch.h | 2 | ||||
-rw-r--r-- | src/util.c | 23 | ||||
-rw-r--r-- | src/util.h | 2 |
5 files changed, 86 insertions, 26 deletions
@@ -1,5 +1,13 @@ 2009-04-29 Andreas Gruenbacher <agruen@suse.de> + * src/pch.c (p_copy, p_rename): New variables. + (pch_copy, pch_rename): New functions. + (intuit_diff_type): Parse the "copy from", "copy to", "rename from", + and "rename to" headers. + * src/util.c (fetchname): Return the fetched name per reference (after + freeing the previous name if any). Also free the previous timestamp + string if any. + * src/patch.c (main): When a git diff includes a file mode change, change to the new mode. * src/util.c (set_file_attributes): Add a mode parameter. @@ -39,6 +39,8 @@ static int p_says_nonexistent[2]; /* [0] for old file, [1] for new: 2 for nonexistent */ static int p_rfc934_nesting; /* RFC 934 nesting level */ static char *p_name[3]; /* filenames in patch headers */ +bool p_copy[2]; /* Does this patch create a copy? */ +bool p_rename[2]; /* Does this patch rename a file? */ static char *p_timestr[2]; /* timestamps as strings */ static mode_t p_mode[2]; /* file modes */ static off_t p_filesize; /* size of the patch file */ @@ -368,7 +370,11 @@ intuit_diff_type (bool need_header, mode_t *p_file_type) p_timestr[i] = 0; } for (i = OLD; i <= NEW; i++) - p_mode[i] = 0; + { + p_mode[i] = 0; + p_copy[i] = false; + p_rename[i] = false; + } /* Ed and normal format patches don't have filename headers. */ if (diff_type == ED_DIFF || diff_type == NORMAL_DIFF) @@ -451,24 +457,21 @@ intuit_diff_type (bool need_header, mode_t *p_file_type) } if (!stars_last_line && strnEQ(s, "*** ", 4)) { - free (p_name[OLD]); - p_name[OLD] = fetchname (s+4, strippath, &p_timestr[OLD], - &p_timestamp[OLD]); + fetchname (s+4, strippath, &p_name[OLD], &p_timestr[OLD], + &p_timestamp[OLD]); need_header = false; } else if (strnEQ(s, "+++ ", 4)) { /* Swap with NEW below. */ - free (p_name[OLD]); - p_name[OLD] = fetchname (s+4, strippath, &p_timestr[OLD], - &p_timestamp[OLD]); + fetchname (s+4, strippath, &p_name[OLD], &p_timestr[OLD], + &p_timestamp[OLD]); need_header = false; p_strip_trailing_cr = strip_trailing_cr; } else if (strnEQ(s, "Index:", 6)) { - free (p_name[INDEX]); - p_name[INDEX] = fetchname (s+6, strippath, (char **) 0, NULL); + fetchname (s+6, strippath, &p_name[INDEX], (char **) 0, NULL); need_header = false; p_strip_trailing_cr = strip_trailing_cr; } @@ -513,11 +516,14 @@ intuit_diff_type (bool need_header, mode_t *p_file_type) goto scan_exit; } - if (! ((free (p_name[OLD]), - (p_name[OLD] = parse_name (s + 11, strippath, &u))) + for (i = OLD; i <= NEW; i++) + { + free (p_name[i]); + p_name[i] = 0; + } + if (! ((p_name[OLD] = parse_name (s + 11, strippath, &u)) && ISSPACE (*u) - && (free (p_name[NEW]), - (p_name[NEW] = parse_name (u, strippath, &u))) + && (p_name[NEW] = parse_name (u, strippath, &u)) && (u = skip_spaces (u), ! *u))) for (i = OLD; i <= NEW; i++) { @@ -558,6 +564,34 @@ intuit_diff_type (bool need_header, mode_t *p_file_type) p_says_nonexistent[OLD] = 2; extended_headers = true; } + else if (git_diff && strnEQ (s, "rename from ", 12)) + { + /* Git leaves out the prefix in the file name in this header, + so we can only ignore the file name. */ + p_rename[OLD] = true; + extended_headers = true; + } + else if (git_diff && strnEQ (s, "rename to ", 10)) + { + /* Git leaves out the prefix in the file name in this header, + so we can only ignore the file name. */ + p_rename[NEW] = true; + extended_headers = true; + } + else if (git_diff && strnEQ (s, "copy from ", 10)) + { + /* Git leaves out the prefix in the file name in this header, + so we can only ignore the file name. */ + p_copy[OLD] = true; + extended_headers = true; + } + else if (git_diff && strnEQ (s, "copy to ", 8)) + { + /* Git leaves out the prefix in the file name in this header, + so we can only ignore the file name. */ + p_copy[NEW] = true; + extended_headers = true; + } else if (git_diff && strnEQ (s, "GIT binary patch", 16)) { p_start = this_line; @@ -573,9 +607,8 @@ intuit_diff_type (bool need_header, mode_t *p_file_type) { struct timespec timestamp; timestamp.tv_sec = -1; - free (p_name[NEW]); - p_name[NEW] = fetchname (t+4, strippath, &p_timestr[NEW], - ×tamp); + fetchname (t+4, strippath, &p_name[NEW], &p_timestr[NEW], + ×tamp); need_header = false; if (timestamp.tv_sec != -1) { @@ -2006,6 +2039,18 @@ pch_name (enum nametype type) return type == NONE ? NULL : p_name[type]; } +bool pch_copy (void) +{ + return p_copy[OLD] && p_copy[NEW] + && p_name[OLD] && p_name[NEW]; +} + +bool pch_rename (void) +{ + return p_rename[OLD] && p_rename[NEW] + && p_name[OLD] && p_name[NEW]; +} + /* Return the specified line position in the old file of the old context. */ lin @@ -40,6 +40,8 @@ int another_hunk (enum diff, bool); int pch_says_nonexistent (bool); size_t pch_line_len (lin); const char *pch_name(enum nametype); +bool pch_copy (void); +bool pch_rename (void); void do_ed_script (FILE *); void open_patch_file (char const *); void re_patch (void); @@ -1316,12 +1316,13 @@ strip_leading_slashes (char *name, int strip_leading) /* Make filenames more reasonable. */ -char * -fetchname (char const *at, int strip_leading, char **ptimestr, +void +fetchname (char const *at, int strip_leading, char **pname, char **ptimestr, struct timespec *pstamp) { char *name; const char *t; + char *timestr = NULL; struct timespec stamp; stamp.tv_sec = -1; @@ -1338,7 +1339,7 @@ fetchname (char const *at, int strip_leading, char **ptimestr, { if (debug & 128) say ("ignoring malformed filename %s\n", quotearg (at)); - return 0; + return; } } else @@ -1372,19 +1373,18 @@ fetchname (char const *at, int strip_leading, char **ptimestr, pstamp->tv_sec = 0; pstamp->tv_nsec = 0; } - return 0; + return; } /* Ignore the name if it doesn't have enough slashes to strip off. */ if (! strip_leading_slashes (name, strip_leading)) { free (name); - return 0; + return; } if (ptimestr) { - char *timestr; char const *u = t + strlen (t); if (u != t && *(u-1) == '\n') @@ -1393,7 +1393,6 @@ fetchname (char const *at, int strip_leading, char **ptimestr, u--; timestr = savebuf (t, u - t + 1); timestr[u - t] = 0; - *ptimestr = timestr; } if (*t == '\n') @@ -1403,7 +1402,7 @@ fetchname (char const *at, int strip_leading, char **ptimestr, if (! pstamp) { free (name); - return 0; + return; } if (set_time | set_utc) @@ -1426,9 +1425,15 @@ fetchname (char const *at, int strip_leading, char **ptimestr, } } + free (*pname); + *pname = name; + if (ptimestr) + { + free (*ptimestr); + *ptimestr = timestr; + } if (pstamp) *pstamp = stamp; - return name; } char * @@ -38,7 +38,7 @@ void fatal (char const *, ...) void pfatal (char const *, ...) __attribute__ ((noreturn, format (printf, 1, 2))); -char *fetchname (char const *, int, char **, struct timespec *); +void fetchname (char const *, int, char **, char **, struct timespec *); char *parse_name (char const *, int, char const **); char *savebuf (char const *, size_t); char *savestr (char const *); |