compat/poll: sleep 1 millisecond to avoid busy wait
[gitweb.git] / builtin / log.c
index 873af6947671d2ed47d74569e5833ebd9fb68fdd..39e883635279ad21f3ddd7b224f484b9b04700b0 100644 (file)
@@ -111,6 +111,7 @@ static void cmd_log_init_defaults(struct rev_info *rev)
 
        if (default_date_mode)
                rev->date_mode = parse_date_format(default_date_mode);
+       rev->diffopt.touched_flags = 0;
 }
 
 static void cmd_log_init_finish(int argc, const char **argv, const char *prefix,
@@ -121,7 +122,7 @@ static void cmd_log_init_finish(int argc, const char **argv, const char *prefix,
        static struct line_opt_callback_data line_cb = {NULL, NULL, STRING_LIST_INIT_DUP};
 
        const struct option builtin_log_options[] = {
-               OPT_BOOL(0, "quiet", &quiet, N_("suppress diff output")),
+               OPT__QUIET(&quiet, N_("suppress diff output")),
                OPT_BOOL(0, "source", &source, N_("show source")),
                OPT_BOOL(0, "use-mailmap", &mailmap, N_("Use mail map file")),
                { OPTION_CALLBACK, 0, "decorate", NULL, NULL, N_("decorate options"),
@@ -390,7 +391,7 @@ static int git_log_config(const char *var, const char *value, void *cb)
                default_show_root = git_config_bool(var, value);
                return 0;
        }
-       if (!prefixcmp(var, "color.decorate."))
+       if (starts_with(var, "color.decorate."))
                return parse_decorate_color_config(var, 15, value);
        if (!strcmp(var, "log.mailmap")) {
                use_mailmap_config = git_config_bool(var, value);
@@ -436,10 +437,29 @@ static void show_tagger(char *buf, int len, struct rev_info *rev)
        strbuf_release(&out);
 }
 
-static int show_blob_object(const unsigned char *sha1, struct rev_info *rev)
+static int show_blob_object(const unsigned char *sha1, struct rev_info *rev, const char *obj_name)
 {
+       unsigned char sha1c[20];
+       struct object_context obj_context;
+       char *buf;
+       unsigned long size;
+
        fflush(stdout);
-       return stream_blob_to_fd(1, sha1, NULL, 0);
+       if (!DIFF_OPT_TOUCHED(&rev->diffopt, ALLOW_TEXTCONV) ||
+           !DIFF_OPT_TST(&rev->diffopt, ALLOW_TEXTCONV))
+               return stream_blob_to_fd(1, sha1, NULL, 0);
+
+       if (get_sha1_with_context(obj_name, 0, sha1c, &obj_context))
+               die("Not a valid object name %s", obj_name);
+       if (!obj_context.path[0] ||
+           !textconv_object(obj_context.path, obj_context.mode, sha1c, 1, &buf, &size))
+               return stream_blob_to_fd(1, sha1, NULL, 0);
+
+       if (!buf)
+               die("git show %s: bad file", obj_name);
+
+       write_or_die(1, buf, size);
+       return 0;
 }
 
 static int show_tag_object(const unsigned char *sha1, struct rev_info *rev)
@@ -457,7 +477,7 @@ static int show_tag_object(const unsigned char *sha1, struct rev_info *rev)
                int new_offset = offset + 1;
                while (new_offset < size && buf[new_offset++] != '\n')
                        ; /* do nothing */
-               if (!prefixcmp(buf + offset, "tagger "))
+               if (starts_with(buf + offset, "tagger "))
                        show_tagger(buf + offset + 7,
                                    new_offset - offset - 7, rev);
                offset = new_offset;
@@ -483,7 +503,7 @@ static void show_rev_tweak_rev(struct rev_info *rev, struct setup_revision_opt *
                /* There was no "-m" on the command line */
                rev->ignore_merges = 0;
                if (!rev->first_parent_only && !rev->combine_merges) {
-                       /* No "--first-parent", "-c", nor "--cc" */
+                       /* No "--first-parent", "-c", or "--cc" */
                        rev->combine_merges = 1;
                        rev->dense_combined_merges = 1;
                }
@@ -525,7 +545,7 @@ int cmd_show(int argc, const char **argv, const char *prefix)
                const char *name = objects[i].name;
                switch (o->type) {
                case OBJ_BLOB:
-                       ret = show_blob_object(o->sha1, NULL);
+                       ret = show_blob_object(o->sha1, &rev, name);
                        break;
                case OBJ_TAG: {
                        struct tag *t = (struct tag *)o;
@@ -862,7 +882,7 @@ static char *find_branch_name(struct rev_info *rev)
        ref = rev->cmdline.rev[positive].name;
        tip_sha1 = rev->cmdline.rev[positive].item->sha1;
        if (dwim_ref(ref, strlen(ref), branch_sha1, &full_ref) &&
-           !prefixcmp(full_ref, "refs/heads/") &&
+           starts_with(full_ref, "refs/heads/") &&
            !hashcmp(tip_sha1, branch_sha1))
                branch = xstrdup(full_ref + strlen("refs/heads/"));
        free(full_ref);
@@ -1112,6 +1132,21 @@ static int cc_callback(const struct option *opt, const char *arg, int unset)
        return 0;
 }
 
+static int from_callback(const struct option *opt, const char *arg, int unset)
+{
+       char **from = opt->value;
+
+       free(*from);
+
+       if (unset)
+               *from = NULL;
+       else if (arg)
+               *from = xstrdup(arg);
+       else
+               *from = xstrdup(git_committer_info(IDENT_NO_DATE));
+       return 0;
+}
+
 int cmd_format_patch(int argc, const char **argv, const char *prefix)
 {
        struct commit *commit;
@@ -1134,6 +1169,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
        int quiet = 0;
        int reroll_count = -1;
        char *branch_name = NULL;
+       char *from = NULL;
        const struct option builtin_format_patch_options[] = {
                { OPTION_CALLBACK, 'n', "numbered", &numbered, NULL,
                            N_("use [PATCH n/m] even with a single patch"),
@@ -1163,13 +1199,13 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
                { OPTION_CALLBACK, 'k', "keep-subject", &rev, NULL,
                            N_("don't strip/add [PATCH]"),
                            PARSE_OPT_NOARG | PARSE_OPT_NONEG, keep_callback },
-               OPT_BOOLEAN(0, "no-binary", &no_binary_diff,
-                           N_("don't output binary diffs")),
-               OPT_BOOLEAN(0, "ignore-if-in-upstream", &ignore_if_in_upstream,
-                           N_("don't include a patch matching a commit upstream")),
-               { OPTION_BOOLEAN, 'p', "no-stat", &use_patch_format, NULL,
+               OPT_BOOL(0, "no-binary", &no_binary_diff,
+                        N_("don't output binary diffs")),
+               OPT_BOOL(0, "ignore-if-in-upstream", &ignore_if_in_upstream,
+                        N_("don't include a patch matching a commit upstream")),
+               { OPTION_SET_INT, 'p', "no-stat", &use_patch_format, NULL,
                  N_("show patch format instead of default (patch + stat)"),
-                 PARSE_OPT_NONEG | PARSE_OPT_NOARG },
+                 PARSE_OPT_NONEG | PARSE_OPT_NOARG, NULL, 1},
                OPT_GROUP(N_("Messaging")),
                { OPTION_CALLBACK, 0, "add-header", NULL, N_("header"),
                            N_("add email header"), 0, header_callback },
@@ -1177,6 +1213,9 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
                            0, to_callback },
                { OPTION_CALLBACK, 0, "cc", NULL, N_("email"), N_("add Cc: header"),
                            0, cc_callback },
+               { OPTION_CALLBACK, 0, "from", &from, N_("ident"),
+                           N_("set From address to <ident> (or committer ident if absent)"),
+                           PARSE_OPT_OPTARG, from_callback },
                OPT_STRING(0, "in-reply-to", &in_reply_to, N_("message-id"),
                            N_("make first mail a reply to <message-id>")),
                { OPTION_CALLBACK, 0, "attach", &rev, N_("boundary"),
@@ -1191,8 +1230,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
                            PARSE_OPT_OPTARG, thread_callback },
                OPT_STRING(0, "signature", &signature, N_("signature"),
                            N_("add a signature")),
-               OPT_BOOLEAN(0, "quiet", &quiet,
-                           N_("don't print the patch filenames")),
+               OPT__QUIET(&quiet, N_("don't print the patch filenames")),
                OPT_END()
        };
 
@@ -1264,6 +1302,11 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
 
        rev.extra_headers = strbuf_detach(&buf, NULL);
 
+       if (from) {
+               if (split_ident_line(&rev.from_ident, from, strlen(from)))
+                       die(_("invalid ident line: %s"), from);
+       }
+
        if (start_number < 0)
                start_number = 1;
 
@@ -1345,7 +1388,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
                        unsigned char sha1[20];
                        const char *ref;
                        ref = resolve_ref_unsafe("HEAD", sha1, 1, NULL);
-                       if (ref && !prefixcmp(ref, "refs/heads/"))
+                       if (ref && starts_with(ref, "refs/heads/"))
                                branch_name = xstrdup(ref + strlen("refs/heads/"));
                        else
                                branch_name = xstrdup(""); /* no branch */