Merge branch 'rc/histogram-diff'
authorJunio C Hamano <gitster@pobox.com>
Thu, 18 Aug 2011 00:36:06 +0000 (17:36 -0700)
committerJunio C Hamano <gitster@pobox.com>
Thu, 18 Aug 2011 00:36:06 +0000 (17:36 -0700)
* rc/histogram-diff:
xdiff/xhistogram: drop need for additional variable
xdiff/xhistogram: rely on xdl_trim_ends()
xdiff/xhistogram: rework handling of recursed results
xdiff: do away with xdl_mmfile_next()
Make test number unique
xdiff/xprepare: use a smaller sample size for histogram diff
xdiff/xprepare: skip classification
teach --histogram to diff
t4033-diff-patience: factor out tests
xdiff/xpatience: factor out fall-back-diff function
xdiff/xprepare: refactor abort cleanups
xdiff/xprepare: use memset()

1  2 
Makefile
diff.c
diff --combined Makefile
index 8dd782fd88d3f1ec3353445ce57cc03c01cf3653,f50d3c777027c1a2318f8ecc042d6ab97541b436..89cc6245a721a1cb807e197fb3346cec02367a51
+++ b/Makefile
@@@ -30,15 -30,15 +30,15 @@@ all:
  # Define LIBPCREDIR=/foo/bar if your libpcre header and library files are in
  # /foo/bar/include and /foo/bar/lib directories.
  #
 -# Define NO_CURL if you do not have libcurl installed.  git-http-pull and
 +# Define NO_CURL if you do not have libcurl installed.  git-http-fetch and
  # git-http-push are not built, and you cannot use http:// and https://
 -# transports.
 +# transports (neither smart nor dumb).
  #
  # Define CURLDIR=/foo/bar if your curl header and library files are in
  # /foo/bar/include and /foo/bar/lib directories.
  #
  # Define NO_EXPAT if you do not have expat installed.  git-http-push is
 -# not built, and you cannot push using http:// and https:// transports.
 +# not built, and you cannot push using http:// and https:// transports (dumb).
  #
  # Define EXPATDIR=/foo/bar if your expat header and library files are in
  # /foo/bar/include and /foo/bar/lib directories.
  #
  # Define NEEDS_SSL_WITH_CRYPTO if you need -lssl when using -lcrypto (Darwin).
  #
 +# Define NEEDS_SSL_WITH_CURL if you need -lssl with -lcurl (Minix).
 +#
 +# Define NEEDS_IDN_WITH_CURL if you need -lidn when using -lcurl (Minix).
 +#
  # Define NEEDS_LIBICONV if linking with libc is not enough (Darwin).
  #
  # Define NEEDS_SOCKET if linking with libc is not enough (SunOS,
  # that tells runtime paths to dynamic libraries;
  # "-Wl,-rpath=/path/lib" is used instead.
  #
 +# Define NO_NORETURN if using buggy versions of gcc 4.6+ and profile feedback,
 +# as the compiler can crash (http://gcc.gnu.org/bugzilla/show_bug.cgi?id=49299)
 +#
  # Define USE_NSEC below if you want git to care about sub-second file mtimes
  # and ctimes. Note that you need recent glibc (at least 2.2.4) for this, and
  # it will BREAK YOUR LOCAL DIFFS! show-diff and anything using it will likely
@@@ -563,7 -556,6 +563,7 @@@ LIB_H += sha1-lookup.
  LIB_H += sideband.h
  LIB_H += sigchain.h
  LIB_H += strbuf.h
 +LIB_H += streaming.h
  LIB_H += string-list.h
  LIB_H += submodule.h
  LIB_H += tag.h
@@@ -670,7 -662,6 +670,7 @@@ LIB_OBJS += shallow.
  LIB_OBJS += sideband.o
  LIB_OBJS += sigchain.o
  LIB_OBJS += strbuf.o
 +LIB_OBJS += streaming.o
  LIB_OBJS += string-list.o
  LIB_OBJS += submodule.o
  LIB_OBJS += symlinks.o
@@@ -1133,6 -1124,8 +1133,6 @@@ endi
        X = .exe
  endif
  ifeq ($(uname_S),Interix)
 -      NO_SYS_POLL_H = YesPlease
 -      NO_INTTYPES_H = YesPlease
        NO_INITGROUPS = YesPlease
        NO_IPV6 = YesPlease
        NO_MEMMEM = YesPlease
        ifeq ($(uname_R),3.5)
                NO_INET_NTOP = YesPlease
                NO_INET_PTON = YesPlease
 +              NO_SOCKADDR_STORAGE = YesPlease
 +              NO_FNMATCH_CASEFOLD = YesPlease
        endif
        ifeq ($(uname_R),5.2)
                NO_INET_NTOP = YesPlease
                NO_INET_PTON = YesPlease
 +              NO_SOCKADDR_STORAGE = YesPlease
 +              NO_FNMATCH_CASEFOLD = YesPlease
        endif
  endif
 +ifeq ($(uname_S),Minix)
 +      NO_IPV6 = YesPlease
 +      NO_ST_BLOCKS_IN_STRUCT_STAT = YesPlease
 +      NO_NSEC = YesPlease
 +      NEEDS_LIBGEN =
 +      NEEDS_CRYPTO_WITH_SSL = YesPlease
 +      NEEDS_IDN_WITH_CURL = YesPlease
 +      NEEDS_SSL_WITH_CURL = YesPlease
 +      NEEDS_RESOLV =
 +      NO_HSTRERROR = YesPlease
 +      NO_MMAP = YesPlease
 +      NO_CURL =
 +      NO_EXPAT =
 +endif
  ifneq (,$(findstring MINGW,$(uname_S)))
        pathsep = ;
        NO_PREAD = YesPlease
        else
                CURL_LIBCURL = -lcurl
        endif
 +      ifdef NEEDS_SSL_WITH_CURL
 +              CURL_LIBCURL += -lssl
 +              ifdef NEEDS_CRYPTO_WITH_SSL
 +                      CURL_LIBCURL += -lcrypto
 +              endif
 +      endif
 +      ifdef NEEDS_IDN_WITH_CURL
 +              CURL_LIBCURL += -lidn
 +      endif
 +
        REMOTE_CURL_PRIMARY = git-remote-http$X
        REMOTE_CURL_ALIASES = git-remote-https$X git-remote-ftp$X git-remote-ftps$X
        REMOTE_CURL_NAMES = $(REMOTE_CURL_PRIMARY) $(REMOTE_CURL_ALIASES)
@@@ -1357,7 -1322,7 +1357,7 @@@ ifndef NO_OPENSS
                OPENSSL_LINK =
        endif
        ifdef NEEDS_CRYPTO_WITH_SSL
 -              OPENSSL_LINK += -lcrypto
 +              OPENSSL_LIBSSL += -lcrypto
        endif
  else
        BASIC_CFLAGS += -DNO_OPENSSL
@@@ -1409,9 -1374,6 +1409,9 @@@ endi
  ifdef USE_ST_TIMESPEC
        BASIC_CFLAGS += -DUSE_ST_TIMESPEC
  endif
 +ifdef NO_NORETURN
 +      BASIC_CFLAGS += -DNO_NORETURN
 +endif
  ifdef NO_NSEC
        BASIC_CFLAGS += -DNO_NSEC
  endif
@@@ -1744,7 -1706,7 +1744,7 @@@ git.sp git.s git.o: EXTRA_CPPFLAGS = -D
        '-DGIT_MAN_PATH="$(mandir_SQ)"' \
        '-DGIT_INFO_PATH="$(infodir_SQ)"'
  
 -git$X: git.o $(BUILTIN_OBJS) $(GITLIBS)
 +git$X: git.o GIT-LDFLAGS $(BUILTIN_OBJS) $(GITLIBS)
        $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ git.o \
                $(BUILTIN_OBJS) $(ALL_LDFLAGS) $(LIBS)
  
@@@ -1876,7 -1838,7 +1876,7 @@@ ifndef NO_CUR
        GIT_OBJS += http.o http-walker.o remote-curl.o
  endif
  XDIFF_OBJS = xdiff/xdiffi.o xdiff/xprepare.o xdiff/xutils.o xdiff/xemit.o \
-       xdiff/xmerge.o xdiff/xpatience.o
+       xdiff/xmerge.o xdiff/xpatience.o xdiff/xhistogram.o
  VCSSVN_OBJS = vcs-svn/string_pool.o vcs-svn/line_buffer.o \
        vcs-svn/repo_tree.o vcs-svn/fast_export.o vcs-svn/svndump.o
  VCSSVN_TEST_OBJS = test-obj-pool.o test-string-pool.o \
@@@ -2042,17 -2004,17 +2042,17 @@@ compat/nedmalloc/nedmalloc.sp compat/ne
        -DNDEBUG -DOVERRIDE_STRDUP -DREPLACE_SYSTEM_ALLOCATOR
  endif
  
 -git-%$X: %.o $(GITLIBS)
 +git-%$X: %.o GIT-LDFLAGS $(GITLIBS)
        $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) $(LIBS)
  
 -git-imap-send$X: imap-send.o $(GITLIBS)
 +git-imap-send$X: imap-send.o GIT-LDFLAGS $(GITLIBS)
        $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \
                $(LIBS) $(OPENSSL_LINK) $(OPENSSL_LIBSSL) $(LIB_4_CRYPTO)
  
 -git-http-fetch$X: revision.o http.o http-walker.o http-fetch.o $(GITLIBS)
 +git-http-fetch$X: revision.o http.o http-walker.o http-fetch.o GIT-LDFLAGS $(GITLIBS)
        $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \
                $(LIBS) $(CURL_LIBCURL)
 -git-http-push$X: revision.o http.o http-push.o $(GITLIBS)
 +git-http-push$X: revision.o http.o http-push.o GIT-LDFLAGS $(GITLIBS)
        $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \
                $(LIBS) $(CURL_LIBCURL) $(EXPAT_LIBEXPAT)
  
@@@ -2062,7 -2024,7 +2062,7 @@@ $(REMOTE_CURL_ALIASES): $(REMOTE_CURL_P
        ln -s $< $@ 2>/dev/null || \
        cp $< $@
  
 -$(REMOTE_CURL_PRIMARY): remote-curl.o http.o http-walker.o $(GITLIBS)
 +$(REMOTE_CURL_PRIMARY): remote-curl.o http.o http-walker.o GIT-LDFLAGS $(GITLIBS)
        $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \
                $(LIBS) $(CURL_LIBCURL) $(EXPAT_LIBEXPAT)
  
@@@ -2132,15 -2094,6 +2132,15 @@@ GIT-CFLAGS: FORC
                echo "$$FLAGS" >GIT-CFLAGS; \
              fi
  
 +TRACK_LDFLAGS = $(subst ','\'',$(ALL_LDFLAGS))
 +
 +GIT-LDFLAGS: FORCE
 +      @FLAGS='$(TRACK_LDFLAGS)'; \
 +          if test x"$$FLAGS" != x"`cat GIT-LDFLAGS 2>/dev/null`" ; then \
 +              echo 1>&2 "    * new link flags"; \
 +              echo "$$FLAGS" >GIT-LDFLAGS; \
 +            fi
 +
  # We need to apply sq twice, once to protect from the shell
  # that runs GIT-BUILD-OPTIONS, and then again to protect it
  # and the first level quoting from the shell that runs "echo".
@@@ -2212,7 -2165,7 +2212,7 @@@ test-svn-fe$X: vcs-svn/lib.
  
  .PRECIOUS: $(TEST_OBJS)
  
 -test-%$X: test-%.o $(GITLIBS)
 +test-%$X: test-%.o GIT-LDFLAGS $(GITLIBS)
        $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) $(filter %.a,$^) $(LIBS)
  
  check-sha1:: test-sha1$X
@@@ -2422,7 -2375,7 +2422,7 @@@ ifndef NO_TCLT
        $(MAKE) -C gitk-git clean
        $(MAKE) -C git-gui clean
  endif
 -      $(RM) GIT-VERSION-FILE GIT-CFLAGS GIT-GUI-VARS GIT-BUILD-OPTIONS
 +      $(RM) GIT-VERSION-FILE GIT-CFLAGS GIT-LDFLAGS GIT-GUI-VARS GIT-BUILD-OPTIONS
  
  .PHONY: all install clean strip
  .PHONY: shell_compatibility_test please_set_SHELL_PATH_to_a_more_modern_shell
@@@ -2533,19 -2486,3 +2533,19 @@@ cover_db: coverage-repor
  
  cover_db_html: cover_db
        cover -report html -outputdir cover_db_html cover_db
 +
 +### profile feedback build
 +#
 +.PHONY: profile-all profile-clean
 +
 +PROFILE_GEN_CFLAGS := $(CFLAGS) -fprofile-generate -DNO_NORETURN=1
 +PROFILE_USE_CFLAGS := $(CFLAGS) -fprofile-use -fprofile-correction -DNO_NORETURN=1
 +
 +profile-clean:
 +      $(RM) $(addsuffix *.gcda,$(object_dirs))
 +      $(RM) $(addsuffix *.gcno,$(object_dirs))
 +
 +profile-all: profile-clean
 +      $(MAKE) CFLAGS="$(PROFILE_GEN_CFLAGS)" all
 +      $(MAKE) CFLAGS="$(PROFILE_GEN_CFLAGS)" -j1 test
 +      $(MAKE) CFLAGS="$(PROFILE_USE_CFLAGS)" all
diff --combined diff.c
index 93ef9a265ca6b52b644468979dba732c70b5097a,1b940ee72e8925ba97d3c162bf5c9da946c6bd0c..d3d8daec77142bc6a67aacdc2e62ee522ddf12db
--- 1/diff.c
--- 2/diff.c
+++ b/diff.c
@@@ -1316,10 -1316,9 +1316,10 @@@ static void show_stats(struct diffstat_
        int i, len, add, del, adds = 0, dels = 0;
        uintmax_t max_change = 0, max_len = 0;
        int total_files = data->nr;
 -      int width, name_width;
 +      int width, name_width, count;
        const char *reset, *add_c, *del_c;
        const char *line_prefix = "";
 +      int extra_shown = 0;
        struct strbuf *msg = NULL;
  
        if (data->nr == 0)
  
        width = options->stat_width ? options->stat_width : 80;
        name_width = options->stat_name_width ? options->stat_name_width : 50;
 +      count = options->stat_count ? options->stat_count : data->nr;
  
        /* Sanity: give at least 5 columns to the graph,
         * but leave at least 10 columns for the name.
        add_c = diff_get_color_opt(options, DIFF_FILE_NEW);
        del_c = diff_get_color_opt(options, DIFF_FILE_OLD);
  
 -      for (i = 0; i < data->nr; i++) {
 +      for (i = 0; (i < count) && (i < data->nr); i++) {
                struct diffstat_file *file = data->files[i];
                uintmax_t change = file->added + file->deleted;
 +              if (!data->files[i]->is_renamed &&
 +                       (change == 0)) {
 +                      count++; /* not shown == room for one more */
 +                      continue;
 +              }
                fill_print_name(file);
                len = strlen(file->print_name);
                if (max_len < len)
                if (max_change < change)
                        max_change = change;
        }
 +      count = i; /* min(count, data->nr) */
  
        /* Compute the width of the graph part;
         * 10 is for one blank at the beginning of the line plus
        else
                width = max_change;
  
 -      for (i = 0; i < data->nr; i++) {
 +      for (i = 0; i < count; i++) {
                const char *prefix = "";
                char *name = data->files[i]->print_name;
                uintmax_t added = data->files[i]->added;
                uintmax_t deleted = data->files[i]->deleted;
                int name_len;
  
 +              if (!data->files[i]->is_renamed &&
 +                       (added + deleted == 0)) {
 +                      total_files--;
 +                      continue;
 +              }
                /*
                 * "scale" the filename
                 */
                        fprintf(options->file, "  Unmerged\n");
                        continue;
                }
 -              else if (!data->files[i]->is_renamed &&
 -                       (added + deleted == 0)) {
 -                      total_files--;
 -                      continue;
 -              }
  
                /*
                 * scale the add/delete
                show_graph(options->file, '-', del, del_c, reset);
                fprintf(options->file, "\n");
        }
 +      for (i = count; i < data->nr; i++) {
 +              uintmax_t added = data->files[i]->added;
 +              uintmax_t deleted = data->files[i]->deleted;
 +              if (!data->files[i]->is_renamed &&
 +                       (added + deleted == 0)) {
 +                      total_files--;
 +                      continue;
 +              }
 +              adds += added;
 +              dels += deleted;
 +              if (!extra_shown)
 +                      fprintf(options->file, "%s ...\n", line_prefix);
 +              extra_shown = 1;
 +      }
        fprintf(options->file, "%s", line_prefix);
        fprintf(options->file,
               " %d files changed, %d insertions(+), %d deletions(-)\n",
@@@ -1861,20 -1839,20 +1861,20 @@@ static unsigned char *deflate_it(char *
  {
        int bound;
        unsigned char *deflated;
 -      z_stream stream;
 +      git_zstream stream;
  
        memset(&stream, 0, sizeof(stream));
 -      deflateInit(&stream, zlib_compression_level);
 -      bound = deflateBound(&stream, size);
 +      git_deflate_init(&stream, zlib_compression_level);
 +      bound = git_deflate_bound(&stream, size);
        deflated = xmalloc(bound);
        stream.next_out = deflated;
        stream.avail_out = bound;
  
        stream.next_in = (unsigned char *)data;
        stream.avail_in = size;
 -      while (deflate(&stream, Z_FINISH) == Z_OK)
 +      while (git_deflate(&stream, Z_FINISH) == Z_OK)
                ; /* nothing */
 -      deflateEnd(&stream);
 +      git_deflate_end(&stream);
        *result_size = stream.total_out;
        return deflated;
  }
@@@ -2006,7 -1984,19 +2006,7 @@@ struct userdiff_driver *get_textconv(st
                return NULL;
  
        diff_filespec_load_driver(one);
 -      if (!one->driver->textconv)
 -              return NULL;
 -
 -      if (one->driver->textconv_want_cache && !one->driver->textconv_cache) {
 -              struct notes_cache *c = xmalloc(sizeof(*c));
 -              struct strbuf name = STRBUF_INIT;
 -
 -              strbuf_addf(&name, "textconv/%s", one->driver->name);
 -              notes_cache_init(c, name.buf, one->driver->textconv);
 -              one->driver->textconv_cache = c;
 -      }
 -
 -      return one->driver;
 +      return userdiff_get_textconv(one->driver);
  }
  
  static void builtin_diff(const char *name_a,
@@@ -3230,7 -3220,6 +3230,7 @@@ static int stat_opt(struct diff_option
        char *end;
        int width = options->stat_width;
        int name_width = options->stat_name_width;
 +      int count = options->stat_count;
        int argcount = 1;
  
        arg += strlen("--stat");
                                name_width = strtoul(av[1], &end, 10);
                                argcount = 2;
                        }
 +              } else if (!prefixcmp(arg, "-count")) {
 +                      arg += strlen("-count");
 +                      if (*arg == '=')
 +                              count = strtoul(arg + 1, &end, 10);
 +                      else if (!*arg && !av[1])
 +                              die("Option '--stat-count' requires a value");
 +                      else if (!*arg) {
 +                              count = strtoul(av[1], &end, 10);
 +                              argcount = 2;
 +                      }
                }
                break;
        case '=':
                width = strtoul(arg+1, &end, 10);
                if (*end == ',')
                        name_width = strtoul(end+1, &end, 10);
 +              if (*end == ',')
 +                      count = strtoul(end+1, &end, 10);
        }
  
        /* Important! This checks all the error cases! */
        options->output_format |= DIFF_FORMAT_DIFFSTAT;
        options->stat_name_width = name_width;
        options->stat_width = width;
 +      options->stat_count = count;
        return argcount;
  }
  
@@@ -3349,7 -3325,7 +3349,7 @@@ int diff_opt_parse(struct diff_options 
        else if (!strcmp(arg, "-s"))
                options->output_format |= DIFF_FORMAT_NO_OUTPUT;
        else if (!prefixcmp(arg, "--stat"))
 -              /* --stat, --stat-width, or --stat-name-width */
 +              /* --stat, --stat-width, --stat-name-width, or --stat-count */
                return stat_opt(options, av);
  
        /* renames options */
                DIFF_XDL_SET(options, IGNORE_WHITESPACE_AT_EOL);
        else if (!strcmp(arg, "--patience"))
                DIFF_XDL_SET(options, PATIENCE_DIFF);
+       else if (!strcmp(arg, "--histogram"))
+               DIFF_XDL_SET(options, HISTOGRAM_DIFF);
  
        /* flags options */
        else if (!strcmp(arg, "--binary")) {