Merge branch 'rs/apply-epoch' into next
authorJunio C Hamano <gitster@pobox.com>
Sun, 27 Aug 2017 06:01:30 +0000 (23:01 -0700)
committerJunio C Hamano <gitster@pobox.com>
Sun, 27 Aug 2017 06:01:30 +0000 (23:01 -0700)
Code simplification.

* rs/apply-epoch:
apply: remove epoch date from regex
apply: check date of potential epoch timestamps first

1  2 
apply.c
diff --combined apply.c
index 86666217d4df0c8162c8d93d859ab5112c10f4b9,3997f73a185f20368c1aa33cabd32bf91f00bc53..71cbbd141c73bd72778d71e1e2400413c11f492f
+++ b/apply.c
@@@ -80,6 -80,7 +80,6 @@@ int init_apply_state(struct apply_stat
  {
        memset(state, 0, sizeof(*state));
        state->prefix = prefix;
 -      state->prefix_length = state->prefix ? strlen(state->prefix) : 0;
        state->lock_file = lock_file;
        state->newfd = -1;
        state->apply = 1;
@@@ -219,7 -220,6 +219,7 @@@ struct patch 
        unsigned int recount:1;
        unsigned int conflicted_threeway:1;
        unsigned int direct_to_threeway:1;
 +      unsigned int crlf_in_old:1;
        struct fragment *fragments;
        char *result;
        size_t resultsize;
@@@ -786,11 -786,11 +786,11 @@@ static int guess_p_value(struct apply_s
                 * Does it begin with "a/$our-prefix" and such?  Then this is
                 * very likely to apply to our directory.
                 */
 -              if (!strncmp(name, state->prefix, state->prefix_length))
 +              if (starts_with(name, state->prefix))
                        val = count_slashes(state->prefix);
                else {
                        cp++;
 -                      if (!strncmp(cp, state->prefix, state->prefix_length))
 +                      if (starts_with(cp, state->prefix))
                                val = count_slashes(state->prefix) + 1;
                }
        }
@@@ -812,16 -812,13 +812,13 @@@ static int has_epoch_timestamp(const ch
         * 1970-01-01, and the seconds part must be "00".
         */
        const char stamp_regexp[] =
-               "^(1969-12-31|1970-01-01)"
-               " "
-               "[0-2][0-9]:[0-5][0-9]:00(\\.0+)?"
+               "^[0-2][0-9]:([0-5][0-9]):00(\\.0+)?"
                " "
                "([-+][0-2][0-9]:?[0-5][0-9])\n";
        const char *timestamp = NULL, *cp, *colon;
        static regex_t *stamp;
        regmatch_t m[10];
-       int zoneoffset;
-       int hourminute;
+       int zoneoffset, epoch_hour, hour, minute;
        int status;
  
        for (cp = nameline; *cp != '\n'; cp++) {
        }
        if (!timestamp)
                return 0;
+       /*
+        * YYYY-MM-DD hh:mm:ss must be from either 1969-12-31
+        * (west of GMT) or 1970-01-01 (east of GMT)
+        */
+       if (skip_prefix(timestamp, "1969-12-31 ", &timestamp))
+               epoch_hour = 24;
+       else if (skip_prefix(timestamp, "1970-01-01 ", &timestamp))
+               epoch_hour = 0;
+       else
+               return 0;
        if (!stamp) {
                stamp = xmalloc(sizeof(*stamp));
                if (regcomp(stamp, stamp_regexp, REG_EXTENDED)) {
                return 0;
        }
  
+       hour = strtol(timestamp, NULL, 10);
+       minute = strtol(timestamp + m[1].rm_so, NULL, 10);
        zoneoffset = strtol(timestamp + m[3].rm_so + 1, (char **) &colon, 10);
        if (*colon == ':')
                zoneoffset = zoneoffset * 60 + strtol(colon + 1, NULL, 10);
        if (timestamp[m[3].rm_so] == '-')
                zoneoffset = -zoneoffset;
  
-       /*
-        * YYYY-MM-DD hh:mm:ss must be from either 1969-12-31
-        * (west of GMT) or 1970-01-01 (east of GMT)
-        */
-       if ((zoneoffset < 0 && memcmp(timestamp, "1969-12-31", 10)) ||
-           (0 <= zoneoffset && memcmp(timestamp, "1970-01-01", 10)))
-               return 0;
-       hourminute = (strtol(timestamp + 11, NULL, 10) * 60 +
-                     strtol(timestamp + 14, NULL, 10) -
-                     zoneoffset);
-       return ((zoneoffset < 0 && hourminute == 1440) ||
-               (0 <= zoneoffset && !hourminute));
+       return hour * 60 + minute - zoneoffset == epoch_hour * 60;
  }
  
  /*
@@@ -1662,19 -1661,6 +1661,19 @@@ static void check_whitespace(struct app
        record_ws_error(state, result, line + 1, len - 2, state->linenr);
  }
  
 +/*
 + * Check if the patch has context lines with CRLF or
 + * the patch wants to remove lines with CRLF.
 + */
 +static void check_old_for_crlf(struct patch *patch, const char *line, int len)
 +{
 +      if (len >= 2 && line[len-1] == '\n' && line[len-2] == '\r') {
 +              patch->ws_rule |= WS_CR_AT_EOL;
 +              patch->crlf_in_old = 1;
 +      }
 +}
 +
 +
  /*
   * Parse a unified diff. Note that this really needs to parse each
   * fragment separately, since the only way to know the difference
@@@ -1725,14 -1711,11 +1724,14 @@@ static int parse_fragment(struct apply_
                        if (!deleted && !added)
                                leading++;
                        trailing++;
 +                      check_old_for_crlf(patch, line, len);
                        if (!state->apply_in_reverse &&
                            state->ws_error_action == correct_ws_error)
                                check_whitespace(state, line, len, patch->ws_rule);
                        break;
                case '-':
 +                      if (!state->apply_in_reverse)
 +                              check_old_for_crlf(patch, line, len);
                        if (state->apply_in_reverse &&
                            state->ws_error_action != nowarn_ws_error)
                                check_whitespace(state, line, len, patch->ws_rule);
                        trailing = 0;
                        break;
                case '+':
 +                      if (state->apply_in_reverse)
 +                              check_old_for_crlf(patch, line, len);
                        if (!state->apply_in_reverse &&
                            state->ws_error_action != nowarn_ws_error)
                                check_whitespace(state, line, len, patch->ws_rule);
@@@ -2107,9 -2088,10 +2106,9 @@@ static int use_patch(struct apply_stat
        int i;
  
        /* Paths outside are not touched regardless of "--include" */
 -      if (0 < state->prefix_length) {
 -              int pathlen = strlen(pathname);
 -              if (pathlen <= state->prefix_length ||
 -                  memcmp(state->prefix, pathname, state->prefix_length))
 +      if (state->prefix && *state->prefix) {
 +              const char *rest;
 +              if (!skip_prefix(pathname, state->prefix, &rest) || !*rest)
                        return 0;
        }
  
@@@ -2285,11 -2267,8 +2284,11 @@@ static void show_stats(struct apply_sta
                add, pluses, del, minuses);
  }
  
 -static int read_old_data(struct stat *st, const char *path, struct strbuf *buf)
 +static int read_old_data(struct stat *st, struct patch *patch,
 +                       const char *path, struct strbuf *buf)
  {
 +      enum safe_crlf safe_crlf = patch->crlf_in_old ?
 +              SAFE_CRLF_KEEP_CRLF : SAFE_CRLF_RENORMALIZE;
        switch (st->st_mode & S_IFMT) {
        case S_IFLNK:
                if (strbuf_readlink(buf, path, st->st_size) < 0)
        case S_IFREG:
                if (strbuf_read_file(buf, path, st->st_size) != st->st_size)
                        return error(_("unable to open or read %s"), path);
 -              convert_to_git(&the_index, path, buf->buf, buf->len, buf, 0);
 +              /*
 +               * "git apply" without "--index/--cached" should never look
 +               * at the index; the target file may not have been added to
 +               * the index yet, and we may not even be in any Git repository.
 +               * Pass NULL to convert_to_git() to stress this; the function
 +               * should never look at the index when explicit crlf option
 +               * is given.
 +               */
 +              convert_to_git(NULL, path, buf->buf, buf->len, buf, safe_crlf);
                return 0;
        default:
                return -1;
@@@ -3409,7 -3380,6 +3408,7 @@@ static int load_patch_target(struct app
                             struct strbuf *buf,
                             const struct cache_entry *ce,
                             struct stat *st,
 +                           struct patch *patch,
                             const char *name,
                             unsigned expected_mode)
  {
                } else if (has_symlink_leading_path(name, strlen(name))) {
                        return error(_("reading from '%s' beyond a symbolic link"), name);
                } else {
 -                      if (read_old_data(st, name, buf))
 +                      if (read_old_data(st, patch, name, buf))
                                return error(_("failed to read %s"), name);
                }
        }
@@@ -3458,7 -3428,7 +3457,7 @@@ static int load_preimage(struct apply_s
                /* We have a patched copy in memory; use that. */
                strbuf_add(&buf, previous->result, previous->resultsize);
        } else {
 -              status = load_patch_target(state, &buf, ce, st,
 +              status = load_patch_target(state, &buf, ce, st, patch,
                                           patch->old_name, patch->old_mode);
                if (status < 0)
                        return status;
@@@ -3546,7 -3516,7 +3545,7 @@@ static int load_current(struct apply_st
        if (verify_index_match(ce, &st))
                return error(_("%s: does not match index"), name);
  
 -      status = load_patch_target(state, &buf, ce, &st, name, mode);
 +      status = load_patch_target(state, &buf, ce, &st, patch, name, mode);
        if (status < 0)
                return status;
        else if (status)
@@@ -3577,7 -3547,7 +3576,7 @@@ static int try_threeway(struct apply_st
        /* Preimage the patch was prepared for */
        if (patch->is_new)
                write_sha1_file("", 0, blob_type, pre_oid.hash);
 -      else if (get_sha1(patch->old_sha1_prefix, pre_oid.hash) ||
 +      else if (get_oid(patch->old_sha1_prefix, &pre_oid) ||
                 read_blob_object(&buf, &pre_oid, patch->old_mode))
                return error(_("repository lacks the necessary blob to fall back on 3-way merge."));
  
@@@ -4101,7 -4071,7 +4100,7 @@@ static int build_fake_ancestor(struct a
                        else
                                return error(_("sha1 information is lacking or "
                                               "useless for submodule %s"), name);
 -              } else if (!get_sha1_blob(patch->old_sha1_prefix, oid.hash)) {
 +              } else if (!get_oid_blob(patch->old_sha1_prefix, &oid)) {
                        ; /* ok */
                } else if (!patch->lines_added && !patch->lines_deleted) {
                        /* mode-only change: update the current */