Code

Merge branch 'ks/no-textconv-symlink'
authorJunio C Hamano <gitster@pobox.com>
Wed, 17 Nov 2010 22:59:27 +0000 (14:59 -0800)
committerJunio C Hamano <gitster@pobox.com>
Wed, 17 Nov 2010 22:59:27 +0000 (14:59 -0800)
* ks/no-textconv-symlink:
  blame,cat-file --textconv: Don't assume mode is ``S_IFREF | 0664''
  blame,cat-file: Demonstrate --textconv is wrongly running converter on symlinks
  blame,cat-file: Prepare --textconv tests for correctly-failing conversion program

1  2 
builtin.h
builtin/blame.c
sha1_name.c

diff --combined builtin.h
index f2a25a084736e573f560672fabc9c6214997f437,98b1e85e8b98a2e8f09d95d88f843e9f842701f4..8dd4569b3c06654826c298b6b52dcf2ac17481bb
+++ b/builtin.h
@@@ -7,15 -7,16 +7,15 @@@
  #include "commit.h"
  #include "notes.h"
  
 +#define DEFAULT_MERGE_LOG_LEN 20
 +
  extern const char git_version_string[];
  extern const char git_usage_string[];
  extern const char git_more_info_string[];
  
 -extern void list_common_cmds_help(void);
 -extern const char *help_unknown_cmd(const char *cmd);
  extern void prune_packed_objects(int);
 -extern int fmt_merge_msg(int merge_summary, struct strbuf *in,
 -      struct strbuf *out);
 -extern int fmt_merge_msg_shortlog(struct strbuf *in, struct strbuf *out);
 +extern int fmt_merge_msg(struct strbuf *in, struct strbuf *out,
 +                       int merge_title, int shortlog_len);
  extern int commit_notes(struct notes_tree *t, const char *msg);
  
  struct notes_rewrite_cfg {
@@@ -36,7 -37,7 +36,7 @@@ void finish_copy_notes_for_rewrite(stru
  
  extern int check_pager_config(const char *cmd);
  
- extern int textconv_object(const char *path, const unsigned char *sha1, char **buf, unsigned long *buf_size);
+ extern int textconv_object(const char *path, unsigned mode, const unsigned char *sha1, char **buf, unsigned long *buf_size);
  
  extern int cmd_add(int argc, const char **argv, const char *prefix);
  extern int cmd_annotate(int argc, const char **argv, const char *prefix);
diff --combined builtin/blame.c
index 101535448f2b0405c280387b63f7ce82fb7dd350,173f286b193111c85f692cba13fd4c8c632d46b0..f5fccc1f6767d7386e37f7273c560d0d4491ee91
@@@ -83,6 -83,7 +83,7 @@@ struct origin 
        struct commit *commit;
        mmfile_t file;
        unsigned char blob_sha1[20];
+       unsigned mode;
        char path[FLEX_ARRAY];
  };
  
@@@ -92,6 -93,7 +93,7 @@@
   * Return 1 if the conversion succeeds, 0 otherwise.
   */
  int textconv_object(const char *path,
+                   unsigned mode,
                    const unsigned char *sha1,
                    char **buf,
                    unsigned long *buf_size)
        struct userdiff_driver *textconv;
  
        df = alloc_filespec(path);
-       fill_filespec(df, sha1, S_IFREG | 0664);
+       fill_filespec(df, sha1, mode);
        textconv = get_textconv(df);
        if (!textconv) {
                free_filespec(df);
@@@ -125,7 -127,7 +127,7 @@@ static void fill_origin_blob(struct dif
  
                num_read_blob++;
                if (DIFF_OPT_TST(opt, ALLOW_TEXTCONV) &&
-                   textconv_object(o->path, o->blob_sha1, &file->ptr, &file_size))
+                   textconv_object(o->path, o->mode, o->blob_sha1, &file->ptr, &file_size))
                        ;
                else
                        file->ptr = read_sha1_file(o->blob_sha1, &type, &file_size);
@@@ -313,21 -315,23 +315,23 @@@ static struct origin *get_origin(struc
   * for an origin is also used to pass the blame for the entire file to
   * the parent to detect the case where a child's blob is identical to
   * that of its parent's.
+  *
+  * This also fills origin->mode for corresponding tree path.
   */
- static int fill_blob_sha1(struct origin *origin)
+ static int fill_blob_sha1_and_mode(struct origin *origin)
  {
-       unsigned mode;
        if (!is_null_sha1(origin->blob_sha1))
                return 0;
        if (get_tree_entry(origin->commit->object.sha1,
                           origin->path,
-                          origin->blob_sha1, &mode))
+                          origin->blob_sha1, &origin->mode))
                goto error_out;
        if (sha1_object_info(origin->blob_sha1, NULL) != OBJ_BLOB)
                goto error_out;
        return 0;
   error_out:
        hashclr(origin->blob_sha1);
+       origin->mode = S_IFINVALID;
        return -1;
  }
  
@@@ -360,12 -364,14 +364,14 @@@ static struct origin *find_origin(struc
                        /*
                         * If the origin was newly created (i.e. get_origin
                         * would call make_origin if none is found in the
-                        * scoreboard), it does not know the blob_sha1,
+                        * scoreboard), it does not know the blob_sha1/mode,
                         * so copy it.  Otherwise porigin was in the
-                        * scoreboard and already knows blob_sha1.
+                        * scoreboard and already knows blob_sha1/mode.
                         */
-                       if (porigin->refcnt == 1)
+                       if (porigin->refcnt == 1) {
                                hashcpy(porigin->blob_sha1, cached->blob_sha1);
+                               porigin->mode = cached->mode;
+                       }
                        return porigin;
                }
                /* otherwise it was not very useful; free it */
                /* The path is the same as parent */
                porigin = get_origin(sb, parent, origin->path);
                hashcpy(porigin->blob_sha1, origin->blob_sha1);
+               porigin->mode = origin->mode;
        } else {
                /*
                 * Since origin->path is a pathspec, if the parent
                case 'M':
                        porigin = get_origin(sb, parent, origin->path);
                        hashcpy(porigin->blob_sha1, p->one->sha1);
+                       porigin->mode = p->one->mode;
                        break;
                case 'A':
                case 'T':
  
                cached = make_origin(porigin->commit, porigin->path);
                hashcpy(cached->blob_sha1, porigin->blob_sha1);
+               cached->mode = porigin->mode;
                parent->util = cached;
        }
        return porigin;
@@@ -486,6 -495,7 +495,7 @@@ static struct origin *find_rename(struc
                    !strcmp(p->two->path, origin->path)) {
                        porigin = get_origin(sb, parent, p->one->path);
                        hashcpy(porigin->blob_sha1, p->one->sha1);
+                       porigin->mode = p->one->mode;
                        break;
                }
        }
@@@ -1099,6 -1109,7 +1109,7 @@@ static int find_copy_in_parent(struct s
  
                        norigin = get_origin(sb, parent, p->one->path);
                        hashcpy(norigin->blob_sha1, p->one->sha1);
+                       norigin->mode = p->one->mode;
                        fill_origin_blob(&sb->revs->diffopt, norigin, &file_p);
                        if (!file_p.ptr)
                                continue;
@@@ -1407,8 -1418,7 +1418,8 @@@ static void get_commit_info(struct comm
                            int detailed)
  {
        int len;
 -      char *tmp, *endp, *reencoded, *message;
 +      const char *subject;
 +      char *reencoded, *message;
        static char author_name[1024];
        static char author_mail[1024];
        static char committer_name[1024];
                    &ret->committer_time, &ret->committer_tz);
  
        ret->summary = summary_buf;
 -      tmp = strstr(message, "\n\n");
 -      if (!tmp) {
 -      error_out:
 +      len = find_commit_subject(message, &subject);
 +      if (len && len < sizeof(summary_buf)) {
 +              memcpy(summary_buf, subject, len);
 +              summary_buf[len] = 0;
 +      } else {
                sprintf(summary_buf, "(%s)", sha1_to_hex(commit->object.sha1));
 -              free(reencoded);
 -              return;
        }
 -      tmp += 2;
 -      endp = strchr(tmp, '\n');
 -      if (!endp)
 -              endp = tmp + strlen(tmp);
 -      len = endp - tmp;
 -      if (len >= sizeof(summary_buf) || len == 0)
 -              goto error_out;
 -      memcpy(summary_buf, tmp, len);
 -      summary_buf[len] = 0;
        free(reencoded);
  }
  
@@@ -2075,7 -2094,7 +2086,7 @@@ static struct commit *fake_working_tree
                switch (st.st_mode & S_IFMT) {
                case S_IFREG:
                        if (DIFF_OPT_TST(opt, ALLOW_TEXTCONV) &&
-                           textconv_object(read_from, null_sha1, &buf.buf, &buf_len))
+                           textconv_object(read_from, mode, null_sha1, &buf.buf, &buf_len))
                                buf.len = buf_len;
                        else if (strbuf_read_file(&buf, read_from, st.st_size) != st.st_size)
                                die_errno("cannot open or read '%s'", read_from);
@@@ -2455,11 -2474,11 +2466,11 @@@ parse_done
        }
        else {
                o = get_origin(&sb, sb.final, path);
-               if (fill_blob_sha1(o))
+               if (fill_blob_sha1_and_mode(o))
                        die("no such path %s in %s", path, final_commit_name);
  
                if (DIFF_OPT_TST(&sb.revs->diffopt, ALLOW_TEXTCONV) &&
-                   textconv_object(path, o->blob_sha1, (char **) &sb.final_buf,
+                   textconv_object(path, o->mode, o->blob_sha1, (char **) &sb.final_buf,
                                    &sb.final_buf_size))
                        ;
                else
diff --combined sha1_name.c
index 484081de82928108a23a714a76ea88693e56bdd1,36c9cbf1acd94b4614f1a66e73664910309c279a..3e856b80369c289a3d9399d60ec3be22bbbc6788
@@@ -342,7 -342,7 +342,7 @@@ static int get_sha1_1(const char *name
  
  static int get_sha1_basic(const char *str, int len, unsigned char *sha1)
  {
 -      static const char *warning = "warning: refname '%.*s' is ambiguous.\n";
 +      static const char *warn_msg = "refname '%.*s' is ambiguous.";
        char *real_ref = NULL;
        int refs_found = 0;
        int at, reflog_len;
                return -1;
  
        if (warn_ambiguous_refs && refs_found > 1)
 -              fprintf(stderr, warning, len, str);
 +              warning(warn_msg, len, str);
  
        if (reflog_len) {
                int nth, i;
                if (read_ref_at(real_ref, at_time, nth, sha1, NULL,
                                &co_time, &co_tz, &co_cnt)) {
                        if (at_time)
 -                              fprintf(stderr,
 -                                      "warning: Log for '%.*s' only goes "
 -                                      "back to %s.\n", len, str,
 +                              warning("Log for '%.*s' only goes "
 +                                      "back to %s.", len, str,
                                        show_date(co_time, co_tz, DATE_RFC2822));
 -                      else
 -                              fprintf(stderr,
 -                                      "warning: Log for '%.*s' only has "
 -                                      "%d entries.\n", len, str, co_cnt);
 +                      else {
 +                              free(real_ref);
 +                              die("Log for '%.*s' only has %d entries.",
 +                                  len, str, co_cnt);
 +                      }
                }
        }
  
@@@ -1062,13 -1062,13 +1062,14 @@@ int get_sha1_with_context_1(const char 
        /* sha1:path --> object name of path in ent sha1
         * :path -> object name of path in index
         * :[0-3]:path -> object name of path in index at stage
 +       * :/foo -> recent commit matching foo
         */
        if (name[0] == ':') {
                int stage = 0;
                struct cache_entry *ce;
                int pos;
                if (namelen > 2 && name[1] == '/')
+                       /* don't need mode for commit */
                        return get_sha1_oneline(name + 2, sha1);
                if (namelen < 3 ||
                    name[2] != ':' ||
                                break;
                        if (ce_stage(ce) == stage) {
                                hashcpy(sha1, ce->sha1);
+                               oc->mode = ce->ce_mode;
                                return 0;
                        }
                        pos++;