Mercurial > hg > toybox
changeset 216:5697a3f7c8cf
Make patch's file add actually work, including directory creating and
understanding zero-context hunks.
author | Rob Landley <rob@landley.net> |
---|---|
date | Thu, 27 Dec 2007 21:36:33 -0600 |
parents | 34e36dffd47a |
children | ca48a878255d |
files | lib/lib.c lib/lib.h toys/patch.c |
diffstat | 3 files changed, 60 insertions(+), 17 deletions(-) [+] |
line wrap: on
line diff
--- a/lib/lib.c Mon Dec 24 19:53:20 2007 -0600 +++ b/lib/lib.c Thu Dec 27 21:36:33 2007 -0600 @@ -322,6 +322,33 @@ return path; } +// Ensure entire path exists. +// If mode != -1 set permissions on newly created dirs. +// Requires that path string be writable (for temporary null terminators). +void xmkpath(char *path, int mode) +{ + char *p, old; + mode_t mask; + int rc; + struct stat st; + + for (p = path; ; p++) { + if (!*p || *p == '/') { + old = *p; + *p = rc = 0; + if (stat(path, &st) || !S_ISDIR(st.st_mode)) { + if (mode != -1) { + mask=umask(0); + rc = mkdir(path, mode); + umask(mask); + } else rc = mkdir(path, 0777); + } + *p = old; + if(rc) perror_exit("mkpath '%s'",path); + } + if (!*p) break; + } +} // Find all file in a colon-separated path with access type "type" (generally // X_OK or R_OK). Returns a list of absolute paths to each file found, in // order.
--- a/lib/lib.h Mon Dec 24 19:53:20 2007 -0600 +++ b/lib/lib.h Thu Dec 27 21:36:33 2007 -0600 @@ -73,6 +73,7 @@ char *xgetcwd(void); void xstat(char *path, struct stat *st); char *xabspath(char *path); +void xmkpath(char *path, int mode); struct string_list *find_in_path(char *path, char *filename); void utoa_to_buf(unsigned n, char *buf, unsigned buflen); void itoa_to_buf(int n, char *buf, unsigned buflen);
--- a/toys/patch.c Mon Dec 24 19:53:20 2007 -0600 +++ b/toys/patch.c Thu Dec 27 21:36:33 2007 -0600 @@ -37,7 +37,8 @@ struct double_list *dlist = (struct double_list *)data; if (TT.state && *dlist->data != TT.state) - fdprintf(TT.fileout, "%s\n", dlist->data+(TT.state>1 ? 1 : 0)); + fdprintf(TT.state == 2 ? 2: TT.fileout, + "%s\n", dlist->data+(TT.state>2 ? 1 : 0)); free(dlist->data); free(dlist); } @@ -79,19 +80,22 @@ } else i = 0; } if (i < TT.context) goto fail_hunk; - llist_free(temp->next, do_line); - temp->next = NULL; + if (temp) { + llist_free(temp->next, do_line); + temp->next = NULL; + } - // Search for a place to apply this hunk + // Search for a place to apply this hunk. Match all context lines and + // lines to be removed. plist = TT.plines; buf = NULL; i = 0; - for (;;) { + if (TT.context) for (;;) { char *data = get_line(TT.filein); TT.linenum++; // If the file ended before we found a home for this hunk, fail. - if (!data) break; + if (!data) goto fail_hunk; dlist_add(&buf, data); if (!backwards && *plist->data == "+-"[reverse]) { @@ -110,25 +114,28 @@ plist = TT.plines; } else { plist = plist->next; - if (!plist) { - // Got it. Emit changed data. - TT.state = "-+"[reverse]; - llist_free(TT.plines, do_line); - TT.plines = NULL; - buf->prev->next = NULL; - TT.state = 0; - llist_free(buf, do_line); - return; - } + if (!plist) break; } } + + // Got it. Emit changed data. + TT.state = "-+"[reverse]; + llist_free(TT.plines, do_line); + TT.plines = NULL; + TT.state = 0; + if (buf) { + buf->prev->next = NULL; + llist_free(buf, do_line); + } + return; + fail_hunk: printf("Hunk FAILED.\n"); // If we got to this point, we've seeked to the end. Discard changes to // this file and advance to next file. - TT.state = 0; + TT.state = 2; llist_free(TT.plines, do_line); TT.plines = 0; if (buf) { @@ -137,6 +144,7 @@ } delete_tempfile(TT.filein, TT.fileout, &TT.tempname); TT.filein = -1; + TT.state = 0; } // state 0: Not in a hunk, look for +++. @@ -181,6 +189,7 @@ // Trim date from end of filename (if any). We don't care. for (s = patchline+4; *s && *s!='\t'; s++) if (*s=='\\' && s[1]) s++; + *s = 0; TT.oldname = xstrdup(patchline+4); } else if (!strncmp("+++ ", patchline, 4)) { @@ -219,6 +228,12 @@ // If the old file was null, we're creating a new one. if (!strcmp(TT.oldname, "/dev/null")) { printf("creating %s\n", start); + s = strrchr(start, '/'); + if (s) { + *s = 0; + xmkpath(start, -1); + *s = '/'; + } TT.filein = xcreate(start, O_CREAT|O_RDWR, 0666); } else { printf("patching %s\n", start);