push: support pushing HEAD to real branch name
[gitweb.git] / builtin-log.c
index 4e9d0cb69ca52ed3a695daa03f9451af6d732bbf..e1f1cf67143721933010065130adaba8723b272b 100644 (file)
@@ -55,13 +55,13 @@ static void cmd_log_init(int argc, const char **argv, const char *prefix,
        rev->abbrev = DEFAULT_ABBREV;
        rev->commit_format = CMIT_FMT_DEFAULT;
        rev->verbose_header = 1;
-       rev->diffopt.recursive = 1;
+       DIFF_OPT_SET(&rev->diffopt, RECURSIVE);
        rev->show_root_diff = default_show_root;
        rev->subject_prefix = fmt_patch_subject_prefix;
        argc = setup_revisions(argc, argv, rev, "HEAD");
        if (rev->diffopt.pickaxe || rev->diffopt.filter)
                rev->always_show_header = 0;
-       if (rev->diffopt.follow_renames) {
+       if (DIFF_OPT_TST(&rev->diffopt, FOLLOW_RENAMES)) {
                rev->always_show_header = 0;
                if (rev->diffopt.nr_paths != 1)
                        usage("git logs can only follow renames on one pathname at a time");
@@ -77,17 +77,79 @@ static void cmd_log_init(int argc, const char **argv, const char *prefix,
        }
 }
 
+/*
+ * This gives a rough estimate for how many commits we
+ * will print out in the list.
+ */
+static int estimate_commit_count(struct rev_info *rev, struct commit_list *list)
+{
+       int n = 0;
+
+       while (list) {
+               struct commit *commit = list->item;
+               unsigned int flags = commit->object.flags;
+               list = list->next;
+               if (!(flags & (TREESAME | UNINTERESTING)))
+                       n++;
+       }
+       return n;
+}
+
+static void show_early_header(struct rev_info *rev, const char *stage, int nr)
+{
+       if (rev->shown_one) {
+               rev->shown_one = 0;
+               if (rev->commit_format != CMIT_FMT_ONELINE)
+                       putchar(rev->diffopt.line_termination);
+       }
+       printf("Final output: %d %s\n", nr, stage);
+}
+
+struct itimerval early_output_timer;
+
 static void log_show_early(struct rev_info *revs, struct commit_list *list)
 {
        int i = revs->early_output;
+       int show_header = 1;
 
        sort_in_topological_order(&list, revs->lifo);
        while (list && i) {
                struct commit *commit = list->item;
-               log_tree_commit(revs, commit);
+               switch (simplify_commit(revs, commit)) {
+               case commit_show:
+                       if (show_header) {
+                               int n = estimate_commit_count(revs, list);
+                               show_early_header(revs, "incomplete", n);
+                               show_header = 0;
+                       }
+                       log_tree_commit(revs, commit);
+                       i--;
+                       break;
+               case commit_ignore:
+                       break;
+               case commit_error:
+                       return;
+               }
                list = list->next;
-               i--;
        }
+
+       /* Did we already get enough commits for the early output? */
+       if (!i)
+               return;
+
+       /*
+        * ..if no, then repeat it twice a second until we
+        * do.
+        *
+        * NOTE! We don't use "it_interval", because if the
+        * reader isn't listening, we want our output to be
+        * throttled by the writing, and not have the timer
+        * trigger every second even if we're blocked on a
+        * reader!
+        */
+       early_output_timer.it_value.tv_sec = 0;
+       early_output_timer.it_value.tv_usec = 500000;
+       setitimer(ITIMER_REAL, &early_output_timer, NULL);
 }
 
 static void early_output(int signal)
@@ -98,7 +160,6 @@ static void early_output(int signal)
 static void setup_early_output(struct rev_info *rev)
 {
        struct sigaction sa;
-       struct itimerval v;
 
        /*
         * Set up the signal handler, minimally intrusively:
@@ -120,21 +181,16 @@ static void setup_early_output(struct rev_info *rev)
         *
         * This is a one-time-only trigger.
         */
-       memset(&v, 0, sizeof(v));
-       v.it_value.tv_sec = 0;
-       v.it_value.tv_usec = 100000;
-       setitimer(ITIMER_REAL, &v, NULL);
+       early_output_timer.it_value.tv_sec = 0;
+       early_output_timer.it_value.tv_usec = 100000;
+       setitimer(ITIMER_REAL, &early_output_timer, NULL);
 }
 
 static void finish_early_output(struct rev_info *rev)
 {
+       int n = estimate_commit_count(rev, rev->commits);
        signal(SIGALRM, SIG_IGN);
-       if (rev->shown_one) {
-               rev->shown_one = 0;
-               if (rev->commit_format != CMIT_FMT_ONELINE)
-                       putchar(rev->diffopt.line_termination);
-       }
-       printf("Final output:\n");
+       show_early_header(rev, "done", n);
 }
 
 static int cmd_log_walk(struct rev_info *rev)
@@ -252,11 +308,9 @@ int cmd_show(int argc, const char **argv, const char *prefix)
                        struct tag *t = (struct tag *)o;
 
                        printf("%stag %s%s\n\n",
-                                       diff_get_color(rev.diffopt.color_diff,
-                                               DIFF_COMMIT),
+                                       diff_get_color_opt(&rev.diffopt, DIFF_COMMIT),
                                        t->tag,
-                                       diff_get_color(rev.diffopt.color_diff,
-                                               DIFF_RESET));
+                                       diff_get_color_opt(&rev.diffopt, DIFF_RESET));
                        ret = show_object(o->sha1, 1);
                        objects[i].item = (struct object *)t->tagged;
                        i--;
@@ -264,11 +318,9 @@ int cmd_show(int argc, const char **argv, const char *prefix)
                }
                case OBJ_TREE:
                        printf("%stree %s%s\n\n",
-                                       diff_get_color(rev.diffopt.color_diff,
-                                               DIFF_COMMIT),
+                                       diff_get_color_opt(&rev.diffopt, DIFF_COMMIT),
                                        name,
-                                       diff_get_color(rev.diffopt.color_diff,
-                                               DIFF_RESET));
+                                       diff_get_color_opt(&rev.diffopt, DIFF_RESET));
                        read_tree_recursive((struct tree *)o, "", 0, 0, NULL,
                                        show_tree_object);
                        break;
@@ -340,6 +392,8 @@ static int istitlechar(char c)
 static char *extra_headers = NULL;
 static int extra_headers_size = 0;
 static const char *fmt_patch_suffix = ".patch";
+static int numbered = 0;
+static int auto_number = 0;
 
 static int git_format_config(const char *var, const char *value)
 {
@@ -364,6 +418,15 @@ static int git_format_config(const char *var, const char *value)
        if (!strcmp(var, "diff.color") || !strcmp(var, "color.diff")) {
                return 0;
        }
+       if (!strcmp(var, "format.numbered")) {
+               if (!strcasecmp(value, "auto")) {
+                       auto_number = 1;
+                       return 0;
+               }
+
+               numbered = git_config_bool(var, value);
+               return 0;
+       }
 
        return git_log_config(var, value);
 }
@@ -533,7 +596,6 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
        struct rev_info rev;
        int nr = 0, total, i, j;
        int use_stdout = 0;
-       int numbered = 0;
        int start_number = -1;
        int keep_subject = 0;
        int numbered_files = 0;         /* _just_ numbers */
@@ -554,7 +616,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
        rev.combine_merges = 0;
        rev.ignore_merges = 1;
        rev.diffopt.msg_sep = "";
-       rev.diffopt.recursive = 1;
+       DIFF_OPT_SET(&rev.diffopt, RECURSIVE);
 
        rev.subject_prefix = fmt_patch_subject_prefix;
        rev.extra_headers = extra_headers;
@@ -570,6 +632,11 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
                else if (!strcmp(argv[i], "-n") ||
                                !strcmp(argv[i], "--numbered"))
                        numbered = 1;
+               else if (!strcmp(argv[i], "-N") ||
+                               !strcmp(argv[i], "--no-numbered")) {
+                       numbered = 0;
+                       auto_number = 0;
+               }
                else if (!prefixcmp(argv[i], "--start-number="))
                        start_number = strtol(argv[i] + 15, NULL, 10);
                else if (!strcmp(argv[i], "--numbered-files"))
@@ -657,8 +724,8 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
        if (!rev.diffopt.output_format)
                rev.diffopt.output_format = DIFF_FORMAT_DIFFSTAT | DIFF_FORMAT_SUMMARY | DIFF_FORMAT_PATCH;
 
-       if (!rev.diffopt.text)
-               rev.diffopt.binary = 1;
+       if (!DIFF_OPT_TST(&rev.diffopt, TEXT))
+               DIFF_OPT_SET(&rev.diffopt, BINARY);
 
        if (!output_directory && !use_stdout)
                output_directory = prefix;
@@ -709,6 +776,8 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
                list[nr - 1] = commit;
        }
        total = nr;
+       if (!keep_subject && auto_number && total > 1)
+               numbered = 1;
        if (numbered)
                rev.total = total + start_number - 1;
        rev.add_signoff = add_signoff;
@@ -814,7 +883,7 @@ int cmd_cherry(int argc, const char **argv, const char *prefix)
        revs.diff = 1;
        revs.combine_merges = 0;
        revs.ignore_merges = 1;
-       revs.diffopt.recursive = 1;
+       DIFF_OPT_SET(&revs.diffopt, RECURSIVE);
 
        if (add_pending_commit(head, &revs, 0))
                die("Unknown commit %s", head);