commit 4379a9aae9e70b9b2beaa7c7b31c4033b302069b from: Omar Polo date: Mon May 02 08:38:43 2022 UTC got patch: handle git-style rename diffs extend the support for git-style diffs to include the "pure rename" case, i.e. when a file is renamed without any edits. ok stsp@ commit - 611e8e319eae000b4d691f6c188af95e4de294a7 commit + 4379a9aae9e70b9b2beaa7c7b31c4033b302069b blob - 879b77f8142d65729f38b9389c48cf5a78299027 blob + c002b7faba2228db56fb3106e4ae4bb7b1f4e994 --- libexec/got-read-patch/got-read-patch.c +++ libexec/got-read-patch/got-read-patch.c @@ -123,14 +123,14 @@ filename(const char *at, char **name) } static const struct got_error * -find_patch(FILE *fp) +find_patch(int *empty, FILE *fp) { const struct got_error *err = NULL; char *old = NULL, *new = NULL; char *line = NULL; size_t linesize = 0; ssize_t linelen; - int create, git = 0; + int create, rename = 0, git = 0; while ((linelen = getline(&line, &linesize, fp)) != -1) { /* @@ -141,14 +141,33 @@ find_patch(FILE *fp) if (!strncmp(line, "--- ", 4)) { free(old); err = filename(line+4, &old); + } else if (rename && !strncmp(line, "rename from ", 12)) { + free(old); + err = filename(line+12, &old); } else if (!strncmp(line, "+++ ", 4)) { free(new); err = filename(line+4, &new); - } else if (!strncmp(line, "diff --git a/", 13)) + } else if (rename && !strncmp(line, "rename to ", 10)) { + free(new); + err = filename(line + 10, &new); + } else if (git && !strncmp(line, "similarity index 100%", 21)) + rename = 1; + else if (!strncmp(line, "diff --git a/", 13)) git = 1; if (err) + break; + + /* + * Git-style diffs with "similarity index 100%" don't + * have any hunks and ends with the "rename to foobar" + * line. + */ + if (rename && old != NULL && new != NULL) { + *empty = 1; + err = send_patch(old, new, git); break; + } if (!strncmp(line, "@@ -", 4)) { create = !strncmp(line+4, "0,0", 3); @@ -412,7 +431,7 @@ read_patch(struct imsgbuf *ibuf, int fd) { const struct got_error *err = NULL; FILE *fp; - int ok, patch_found = 0; + int patch_found = 0; if ((fp = fdopen(fd, "r")) == NULL) { err = got_error_from_errno("fdopen"); @@ -421,16 +440,19 @@ read_patch(struct imsgbuf *ibuf, int fd) } while (!feof(fp)) { - err = find_patch(fp); + int empty = 0, ok = 1; + + err = find_patch(&empty, fp); if (err) goto done; patch_found = 1; for (;;) { - err = parse_hunk(fp, &ok); + if (!empty) + err = parse_hunk(fp, &ok); if (err) goto done; - if (!ok) { + if (!ok || empty) { err = send_patch_done(); if (err) goto done; blob - 43981599f51928fd929e8cc47538da750b875b97 blob + b30e9e02052c205e40d442f72d8988369b6eea06 --- regress/cmdline/patch.sh +++ regress/cmdline/patch.sh @@ -647,14 +647,22 @@ test_patch_rename() { fi cat < $testroot/wt/patch +diff --git a/beta b/iota +similarity index 100% +rename from beta +rename to iota diff --git a/alpha b/eta --- a/alpha +++ b/eta -@@ -0,0 +0,0 @@ +@@ -1 +1 @@ +-alpha ++eta EOF - echo 'D alpha' > $testroot/stdout.expected - echo 'A eta' >> $testroot/stdout.expected + echo 'D beta' > $testroot/stdout.expected + echo 'A iota' >> $testroot/stdout.expected + echo 'D alpha' >> $testroot/stdout.expected + echo 'A eta' >> $testroot/stdout.expected (cd $testroot/wt && got patch patch) > $testroot/stdout ret=$? @@ -671,77 +679,35 @@ EOF return 1 fi - if [ -f $testroot/wt/alpha ]; then - echo "alpha was not removed" >&2 + if [ -f $testroot/wt/alpha -o -f $testroot/wt/beta ]; then + echo "alpha or beta were not removed" >&2 test_done $testroot 1 return 1 fi - if [ ! -f $testroot/wt/eta ]; then - echo "eta was not created" >&2 + if [ ! -f $testroot/wt/iota -o ! -f $testroot/wt/eta ]; then + echo "iota or eta were not created" >&2 test_done $testroot 1 return 1 fi - echo alpha > $testroot/wt/eta.expected - cmp -s $testroot/wt/eta.expected $testroot/wt/eta - ret=$? - if [ $ret -ne 0 ]; then - diff -u $testroot/wt/eta.expected $testroot/wt/eta - test_done $testroot $ret - return 1 - fi - - # revert the changes and try again with a rename + edit - (cd $testroot/wt && got revert alpha eta) > /dev/null - ret=$? - if [ $ret -ne 0 ]; then - test_done $testroot $ret - return 1 - fi - rm $testroot/wt/eta - - cat < $testroot/wt/patch -diff --git a/alpha b/eta ---- a/alpha -+++ b/eta -@@ -1 +1,2 @@ - alpha -+but now is eta -EOF - - (cd $testroot/wt && got patch patch) > $testroot/stdout + echo beta > $testroot/wt/iota.expected + cmp -s $testroot/wt/iota.expected $testroot/wt/iota ret=$? if [ $ret -ne 0 ]; then + diff -u $testroot/wt/iota.expected $testroot/wt/iota test_done $testroot $ret return 1 fi - cmp -s $testroot/stdout.expected $testroot/stdout + echo eta > $testroot/wt/eta.expected + cmp -s $testroot/wt/eta.expected $testroot/wt/eta ret=$? if [ $ret -ne 0 ]; then - diff -u $testroot/stdout.expected $testroot/stdout + diff -u $testroot/wt/eta.expected $testroot/wt/eta test_done $testroot $ret return 1 fi - if [ -f $testroot/wt/alpha ]; then - echo "alpha was not removed" >&2 - test_done $testroot 1 - return 1 - fi - if [ ! -f $testroot/wt/eta ]; then - echo "eta was not created" >&2 - test_done $testroot 1 - return 1 - fi - - echo alpha > $testroot/wt/eta.expected - echo 'but now is eta' >> $testroot/wt/eta.expected - cmp -s $testroot/wt/eta.expected $testroot/wt/eta - ret=$? - if [ $ret -ne 0 ]; then - diff -u $testroot/wt/eta.expected $testroot/wt/eta - fi test_done $testroot $ret }