1. 05 Jun, 2020 1 commit
  2. 10 Dec, 2019 1 commit
    • cl_git_fail: do not report bogus error message · d29d4de2
      When we expect a checkout operation to fail, but it succeeds, we
      actually do not want to see the error messages that were generated in
      the meantime for errors that were handled gracefully by the code (e.g.
      when an object could not be found in a pack: in this case, the next
      backend would have been given a chance to look up the object, and
      probably would have found it because the checkout succeeded, after all).
      
      Which means that in the specific case of `cl_git_fail()`, we actually
      want to clear the global error state _after_ evaluating the command: we
      know that any still-available error would be bogus, seeing as the
      command succeeded (unexpectedly).
      
      Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
      Johannes Schindelin committed
  3. 11 Jul, 2019 1 commit
    • config_file: implement stat cache to avoid repeated rehashing · d7f58eab
      To decide whether a config file has changed, we always hash its
      complete contents. This is unnecessarily expensive, as
      well-behaved filesystems will always update stat information for
      files which have changed. So before computing the hash, we should
      first check whether the stat info has actually changed for either
      the configuration file or any of its includes. This avoids having
      to re-read the configuration file and its includes every time
      when we check whether it's been modified.
      
      Tracing the for-each-ref example previous to this commit, one can
      see that we repeatedly re-open both the repo configuration as
      well as the global configuration:
      
      	$ strace lg2 for-each-ref |& grep config
      	access("/home/pks/.gitconfig", F_OK)    = -1 ENOENT (No such file or directory)
      	access("/home/pks/.config/git/config", F_OK) = 0
      	access("/etc/gitconfig", F_OK)          = -1 ENOENT (No such file or directory)
      	stat("/tmp/repo/.git/config", {st_mode=S_IFREG|0644, st_size=92, ...}) = 0
      	access("/tmp/repo/.git/config", F_OK)   = 0
      	stat("/tmp/repo/.git/config", {st_mode=S_IFREG|0644, st_size=92, ...}) = 0
      	open("/tmp/repo/.git/config", O_RDONLY|O_CLOEXEC) = 3
      	stat("/home/pks/.gitconfig", 0x7ffd15c05290) = -1 ENOENT (No such file or directory)
      	access("/home/pks/.gitconfig", F_OK)    = -1 ENOENT (No such file or directory)
      	stat("/home/pks/.config/git/config", {st_mode=S_IFREG|0644, st_size=1154, ...}) = 0
      	access("/home/pks/.config/git/config", F_OK) = 0
      	stat("/home/pks/.config/git/config", {st_mode=S_IFREG|0644, st_size=1154, ...}) = 0
      	open("/home/pks/.config/git/config", O_RDONLY|O_CLOEXEC) = 3
      	stat("/tmp/repo/.git/config", {st_mode=S_IFREG|0644, st_size=92, ...}) = 0
      	open("/tmp/repo/.git/config", O_RDONLY|O_CLOEXEC) = 3
      	stat("/home/pks/.gitconfig", 0x7ffd15c051f0) = -1 ENOENT (No such file or directory)
      	stat("/home/pks/.config/git/config", {st_mode=S_IFREG|0644, st_size=1154, ...}) = 0
      	open("/home/pks/.config/git/config", O_RDONLY|O_CLOEXEC) = 3
      	stat("/tmp/repo/.git/config", {st_mode=S_IFREG|0644, st_size=92, ...}) = 0
      	open("/tmp/repo/.git/config", O_RDONLY|O_CLOEXEC) = 3
      	stat("/home/pks/.gitconfig", 0x7ffd15c05090) = -1 ENOENT (No such file or directory)
      	stat("/home/pks/.config/git/config", {st_mode=S_IFREG|0644, st_size=1154, ...}) = 0
      	open("/home/pks/.config/git/config", O_RDONLY|O_CLOEXEC) = 3
      	stat("/tmp/repo/.git/config", {st_mode=S_IFREG|0644, st_size=92, ...}) = 0
      	open("/tmp/repo/.git/config", O_RDONLY|O_CLOEXEC) = 3
      	stat("/home/pks/.gitconfig", 0x7ffd15c05090) = -1 ENOENT (No such file or directory)
      	stat("/home/pks/.config/git/config", {st_mode=S_IFREG|0644, st_size=1154, ...}) = 0
      	open("/home/pks/.config/git/config", O_RDONLY|O_CLOEXEC) = 3
      	stat("/tmp/repo/.git/config", {st_mode=S_IFREG|0644, st_size=92, ...}) = 0
      	open("/tmp/repo/.git/config", O_RDONLY|O_CLOEXEC) = 3
      	stat("/home/pks/.gitconfig", 0x7ffd15c05090) = -1 ENOENT (No such file or directory)
      	stat("/home/pks/.config/git/config", {st_mode=S_IFREG|0644, st_size=1154, ...}) = 0
      	open("/home/pks/.config/git/config", O_RDONLY|O_CLOEXEC) = 3
      
      With the change, we only do stats for those files and open them a
      single time, only:
      
      	$ strace lg2 for-each-ref |& grep config
      	access("/home/pks/.gitconfig", F_OK)    = -1 ENOENT (No such file or directory)
      	access("/home/pks/.config/git/config", F_OK) = 0
      	access("/etc/gitconfig", F_OK)          = -1 ENOENT (No such file or directory)
      	stat("/tmp/repo/.git/config", {st_mode=S_IFREG|0644, st_size=92, ...}) = 0
      	access("/tmp/repo/.git/config", F_OK)   = 0
      	stat("/tmp/repo/.git/config", {st_mode=S_IFREG|0644, st_size=92, ...}) = 0
      	stat("/tmp/repo/.git/config", {st_mode=S_IFREG|0644, st_size=92, ...}) = 0
      	open("/tmp/repo/.git/config", O_RDONLY|O_CLOEXEC) = 3
      	stat("/home/pks/.gitconfig", 0x7ffe70540d20) = -1 ENOENT (No such file or directory)
      	access("/home/pks/.gitconfig", F_OK)    = -1 ENOENT (No such file or directory)
      	stat("/home/pks/.config/git/config", {st_mode=S_IFREG|0644, st_size=1154, ...}) = 0
      	access("/home/pks/.config/git/config", F_OK) = 0
      	stat("/home/pks/.config/git/config", {st_mode=S_IFREG|0644, st_size=1154, ...}) = 0
      	stat("/home/pks/.config/git/config", {st_mode=S_IFREG|0644, st_size=1154, ...}) = 0
      	open("/home/pks/.config/git/config", O_RDONLY|O_CLOEXEC) = 3
      	stat("/tmp/repo/.git/config", {st_mode=S_IFREG|0644, st_size=92, ...}) = 0
      	stat("/home/pks/.gitconfig", 0x7ffe70540ca0) = -1 ENOENT (No such file or directory)
      	stat("/home/pks/.gitconfig", 0x7ffe70540c80) = -1 ENOENT (No such file or directory)
      	stat("/home/pks/.config/git/config", {st_mode=S_IFREG|0644, st_size=1154, ...}) = 0
      	stat("/tmp/repo/.git/config", {st_mode=S_IFREG|0644, st_size=92, ...}) = 0
      	stat("/home/pks/.gitconfig", 0x7ffe70540b40) = -1 ENOENT (No such file or directory)
      	stat("/home/pks/.gitconfig", 0x7ffe70540b20) = -1 ENOENT (No such file or directory)
      	stat("/home/pks/.config/git/config", {st_mode=S_IFREG|0644, st_size=1154, ...}) = 0
      	stat("/tmp/repo/.git/config", {st_mode=S_IFREG|0644, st_size=92, ...}) = 0
      	stat("/home/pks/.gitconfig", 0x7ffe70540b40) = -1 ENOENT (No such file or directory)
      	stat("/home/pks/.gitconfig", 0x7ffe70540b20) = -1 ENOENT (No such file or directory)
      	stat("/home/pks/.config/git/config", {st_mode=S_IFREG|0644, st_size=1154, ...}) = 0
      	stat("/tmp/repo/.git/config", {st_mode=S_IFREG|0644, st_size=92, ...}) = 0
      	stat("/home/pks/.gitconfig", 0x7ffe70540b40) = -1 ENOENT (No such file or directory)
      	stat("/home/pks/.gitconfig", 0x7ffe70540b20) = -1 ENOENT (No such file or directory)
      	stat("/home/pks/.config/git/config", {st_mode=S_IFREG|0644, st_size=1154, ...}) = 0
      
      The following benchmark has been performed with and without the
      stat cache in a best-of-ten run:
      
      ```
      
      int lg2_repro(git_repository *repo, int argc, char **argv)
      {
      	git_config *cfg;
      	int32_t dummy;
      	int i;
      
      	UNUSED(argc);
      	UNUSED(argv);
      
      	check_lg2(git_repository_config(&cfg, repo),
      			"Could not obtain config", NULL);
      
      	for (i = 1; i < 100000; ++i)
      		git_config_get_int32(&dummy, cfg, "foo.bar");
      
      	git_config_free(cfg);
      	return 0;
      }
      ```
      
      Without stat cache:
      
      	$ time lg2 repro
      	real    0m1.528s
      	user    0m0.568s
      	sys     0m0.944s
      
      With stat cache:
      
      	$ time lg2 repro
      	real    0m0.526s
      	user    0m0.268s
      	sys     0m0.258s
      
      This benchmark shows a nearly three-fold performance improvement.
      
      This change requires that we check our configuration stress tests
      as we're now in fact becoming more racy. If somebody is writing a
      configuration file at nearly the same time (there is a window of
      100ns on Windows-based systems), then it might be that we realize
      that this file has actually changed and thus may not re-read it.
      This will only happen if either an external process is rewriting
      the configuration file or if the same process has multiple
      `git_config` structures pointing to the same time, where one of
      both is being used to write and the other one is used to read
      values.
      Patrick Steinhardt committed
  4. 19 May, 2019 1 commit
  5. 22 Jan, 2019 1 commit
  6. 06 Jan, 2019 1 commit
  7. 29 Jun, 2018 1 commit
  8. 17 Feb, 2017 2 commits
  9. 12 Dec, 2016 1 commit
  10. 18 Nov, 2016 2 commits
  11. 02 Jul, 2015 1 commit
  12. 28 May, 2015 1 commit
  13. 04 Feb, 2015 1 commit
  14. 14 Jan, 2015 1 commit
  15. 05 Aug, 2014 1 commit
  16. 01 Jul, 2014 1 commit
  17. 15 May, 2014 1 commit
    • Better search path sandboxing · 8487e237
      There are a number of tests that modify the global or system
      search paths during the tests.  This adds a helper function to
      make it easier to restore those paths and makes sure that they
      are getting restored in a manner that preserves test isolation.
      Russell Belfer committed
  18. 02 May, 2014 1 commit
    • Improve handling of fake home directory · 0f603132
      There are a few tests that set up a fake home directory and a
      fake GLOBAL search path so that we can test things in global
      ignore or attribute or config files.  This cleans up that code to
      work more robustly even if there is a test failure.  This also
      fixes some valgrind warnings where scanning search paths for
      separators could end up doing a little bit of sketchy data access
      when coming to the end of search list.
      Russell Belfer committed
  19. 22 Apr, 2014 1 commit
  20. 17 Apr, 2014 1 commit
  21. 14 Apr, 2014 1 commit
    • Fix core.excludesfile named .gitignore · a9528b8f
      Ignore rules with slashes in them are matched using FNM_PATHNAME
      and use the path to the .gitignore file from the root of the
      repository along with the path fragment (including slashes) in
      the ignore file itself.  Unfortunately, the relative path to the
      .gitignore file was being applied to the global core.excludesfile
      if that was also named ".gitignore".
      
      This fixes that with more precise matching and includes test for
      ignore rules with leading slashes (which were the primary example
      of this being broken in the real world).
      
      This also backports an improvement to the file context logic from
      the threadsafe-iterators branch where we don't rely on mutating
      the key of the attribute file name to generate the context path.
      Russell Belfer committed
  22. 06 Apr, 2014 1 commit
  23. 09 Feb, 2014 1 commit
  24. 14 Nov, 2013 1 commit
  25. 26 Sep, 2013 1 commit
  26. 24 Sep, 2013 1 commit
  27. 17 Sep, 2013 3 commits
  28. 12 Sep, 2013 1 commit
  29. 04 Sep, 2013 2 commits
  30. 31 Jul, 2013 1 commit
    • Major rename detection changes · d730d3f4
      After doing further profiling, I found that a lot of time was
      being spent attempting to insert hashes into the file hash
      signature when using the rolling hash because the rolling hash
      approach generates a hash per byte of the file instead of one
      per run/line of data.
      
      To optimize this, I decided to convert back to a run-based file
      signature algorithm which would be more like core Git.
      
      After changing this, a number of the existing tests started to
      fail.  In some cases, this appears to have been because the test
      was coded to be too specific to the particular results of the file
      similarity metric and in some cases there appear to have been bugs
      in the core rename detection code where only by the coincidence
      of the file similarity scoring were the expected results being
      generated.
      
      This renames all the variables in the core rename detection code
      to be more consistent and hopefully easier to follow which made it
      a bit easier to reason about the behavior of that code and fix the
      problems that I was seeing.  I think it's in better shape now.
      
      There are a couple of tests now that attempt to stress test the
      rename detection code and they are quite slow.  Most of the time
      is spent setting up the test data on disk and in the index.  When
      we roll out performance improvements for index insertion, it
      should also speed up these tests I hope.
      Russell Belfer committed
  31. 10 Jul, 2013 1 commit
    • Add ignore_submodules to diff options · f9775a37
      This adds correct support for an equivalent to --ignore-submodules
      in diff, where an actual ignore value can be passed to diff to
      override the per submodule settings in the configuration.
      
      This required tweaking the constants for ignore values so that
      zero would not be used and could represent an unset option to the
      diff.  This was an opportunity to move the submodule values into
      include/git2/types.h and to rename the poorly named DEFAULT values
      for ignore and update constants to RESET instead.
      
      Now the GIT_DIFF_IGNORE_SUBMODULES flag is exactly the same as
      setting the ignore_submodules option to GIT_SUBMODULE_IGNORE_ALL
      (which is actually a minor change from the old behavior in that
      submodules will now be treated as UNMODIFIED deltas instead of
      being left out totally - if you set GIT_DIFF_INCLUDE_UNMODIFIED).
      
      This includes tests for the various new settings.
      Russell Belfer committed
  32. 10 May, 2013 1 commit
    • Improve ignore handling in git_status_file · 1f9e41ee
      The git_status_file API was doing a hack to deal with files that
      are inside ignored directories.  The status scan was not reporting
      any file in this case, so git_status_file would attempt a final
      "stat()" call, and return IGNORED if the file actually existed.
      
      On case-insensitive filesystems where core.ignorecase is set
      incorrectly, this magic check can "succeed" and report a file
      as ignored when it should actually return ENOTFOUND.
      
      Now that we have the GIT_STATUS_OPT_RECURSE_IGNORED_DIRS, we can
      use that flag to make sure that git_status_file() will look into
      ignored directories and eliminate the hack completely, so we give
      the correct error.
      Russell Belfer committed
  33. 22 Mar, 2013 2 commits
  34. 04 Jan, 2013 1 commit