1. 30 May, 2018 1 commit
    • attr_file: fix handling of directory patterns with trailing spaces · b260fdc8
      When comparing whether a path matches a directory rule, we pass the
      both the path and directory name to `fnmatch` with
      `GIT_ATTR_FNMATCH_DIRECTORY` being set. `fnmatch` expects the pattern to
      contain no trailing directory '/', which is why we try to always strip
      patterns of trailing slashes. We do not handle that case correctly
      though when the pattern itself has trailing spaces, causing the match to
      fail.
      
      Fix the issue by stripping trailing spaces and tabs for a rule previous
      to checking whether the pattern is a directory pattern with a trailing
      '/'. This replaces the whitespace-stripping in our ignore file parsing
      code, which was stripping whitespaces too late. Add a test to catch
      future breakage.
      Patrick Steinhardt committed
  2. 28 Feb, 2018 1 commit
    • win32: strncmp -> git__strncmp · a33deeb4
      The win32 C library is compiled cdecl, however when configured with
      `STDCALL=ON`, our functions (and function pointers) will use the stdcall
      calling convention.  You cannot set a `__stdcall` function pointer to a
      `__cdecl` function, so it's easier to just use our `git__strncmp`
      instead of sorting that mess out.
      Edward Thomson committed
  3. 01 Feb, 2018 1 commit
    • attr: avoid stat'ting files for bare repositories · e28e17e6
      Depending on whether the path we want to look up an attribute for is a
      file or a directory, the fnmatch function will be called with different
      flags. Because of this, we have to first stat(3) the path to determine
      whether it is a file or directory in `git_attr_path__init`. This is
      wasteful though in bare repositories, where we can already be assured
      that the path will never exist at all due to there being no worktree. In
      this case, we will execute an unnecessary syscall, which might be
      noticeable on networked file systems.
      
      What happens right now is that we always pass the `GIT_DIR_FLAG_UNKOWN`
      flag to `git_attr_path__init`, which causes it to `stat` the file itself
      to determine its type. As it is calling `git_path_isdir` on the path,
      which will always return `false` in case the path does not exist, we end
      up with the path always being treated as a file in case of a bare
      repository. As such, we can just check the bare-repository case in all
      callers and then pass in `GIT_DIR_FLAG_FALSE` ourselves, avoiding the
      need to `stat`. While this may not always be correct, it at least is no
      different from our current behavior.
      Patrick Steinhardt committed
  4. 29 Oct, 2017 1 commit
  5. 25 Aug, 2017 4 commits
    • ignore: honor case insensitivity for negative ignores · 2d9ff8f5
      When computing negative ignores, we throw away any rule which does not
      undo a previous rule to optimize. But on case insensitive file systems,
      we need to keep in mind that a negative ignore can also undo a previous
      rule with different case, which we did not yet honor while determining
      whether a rule undoes a previous one. So in the following example, we
      fail to unignore the "/Case" directory:
      
          /case
          !/Case
      
      Make both paths checking whether a plain- or wildcard-based rule undo a
      previous rule aware of case-insensitivity. This fixes the described
      issue.
      Patrick Steinhardt committed
    • ignore: keep negative rules containing wildcards · b8922fc8
      Ignore rules allow for reverting a previously ignored rule by prefixing
      it with an exclamation mark. As such, a negative rule can only override
      previously ignored files. While computing all ignore patterns, we try to
      use this fact to optimize away some negative rules which do not override
      any previous patterns, as they won't change the outcome anyway.
      
      In some cases, though, this optimization causes us to get the actual
      ignores wrong for some files. This may happen whenever the pattern
      contains a wildcard, as we are unable to reason about whether a pattern
      overrides a previous pattern in a sane way. This happens for example in
      the case where a gitignore file contains "*.c" and "!src/*.c", where we
      wouldn't un-ignore files inside of the "src/" subdirectory.
      
      In this case, the first solution coming to mind may be to just strip the
      "src/" prefix and simply compare the basenames. While that would work
      here, it would stop working as soon as the basename pattern itself is
      different, like for example with "*x.c" and "!src/*.c. As such, we
      settle for the easier fix of just not optimizing away rules that contain
      a wildcard.
      Patrick Steinhardt committed
  6. 03 Jul, 2017 2 commits
    • Make sure to always include "common.h" first · 0c7f49dd
      Next to including several files, our "common.h" header also declares
      various macros which are then used throughout the project. As such, we
      have to make sure to always include this file first in all
      implementation files. Otherwise, we might encounter problems or even
      silent behavioural differences due to macros or defines not being
      defined as they should be. So in fact, our header and implementation
      files should make sure to always include "common.h" first.
      
      This commit does so by establishing a common include pattern. Header
      files inside of "src" will now always include "common.h" as its first
      other file, separated by a newline from all the other includes to make
      it stand out as special. There are two cases for the implementation
      files. If they do have a matching header file, they will always include
      this one first, leading to "common.h" being transitively included as
      first file. If they do not have a matching header file, they instead
      include "common.h" as first file themselves.
      
      This fixes the outlined problems and will become our standard practice
      for header and source files inside of the "src/" from now on.
      Patrick Steinhardt committed
    • Add missing license headers · 2480d0eb
      Some implementation files were missing the license headers. This commit
      adds them.
      Patrick Steinhardt committed
  7. 13 Feb, 2017 1 commit
    • repository: use `git_repository_item_path` · c5f3da96
      The recent introduction of the commondir variable of a repository
      requires callers to distinguish whether their files are part of
      the dot-git directory or the common directory shared between
      multpile worktrees. In order to take the burden from callers and
      unify knowledge on which files reside where, the
      `git_repository_item_path` function has been introduced which
      encapsulate this knowledge.
      
      Modify most existing callers of `git_repository_path` to use
      `git_repository_item_path` instead, thus making them implicitly
      aware of the common directory.
      Patrick Steinhardt committed
  8. 13 Jan, 2017 1 commit
  9. 29 Dec, 2016 1 commit
  10. 12 Aug, 2016 1 commit
    • ignore: allow unignoring basenames in subdirectories · fcb2c1c8
      The .gitignore file allows for patterns which unignore previous
      ignore patterns. When unignoring a previous pattern, there are
      basically three cases how this is matched when no globbing is
      used:
      
      1. when a previous file has been ignored, it can be unignored by
         using its exact name, e.g.
      
         foo/bar
         !foo/bar
      
      2. when a file in a subdirectory has been ignored, it can be
         unignored by using its basename, e.g.
      
         foo/bar
         !bar
      
      3. when all files with a basename are ignored, a specific file
         can be unignored again by specifying its path in a
         subdirectory, e.g.
      
         bar
         !foo/bar
      
      The first problem in libgit2 is that we did not correctly treat
      the second case. While we verified that the negative pattern
      matches the tail of the positive one, we did not verify if it
      only matches the basename of the positive pattern. So e.g. we
      would have also negated a pattern like
      
          foo/fruz_bar
          !bar
      
      Furthermore, we did not check for the third case, where a
      basename is being unignored in a certain subdirectory again.
      
      Both issues are fixed with this commit.
      Patrick Steinhardt committed
  11. 02 Apr, 2016 1 commit
  12. 13 Sep, 2015 1 commit
  13. 24 Aug, 2015 1 commit
  14. 20 May, 2015 1 commit
  15. 28 Apr, 2015 1 commit
  16. 17 Apr, 2015 1 commit
  17. 03 Feb, 2015 1 commit
    • attrcache: don't re-read attrs during checkout · 9f779aac
      During checkout, assume that the .gitattributes files aren't
      modified during the checkout.  Instead, create an "attribute session"
      during checkout.  Assume that attribute data read in the same
      checkout "session" hasn't been modified since the checkout started.
      (But allow subsequent checkouts to invalidate the cache.)
      
      Further, cache nonexistent git_attr_file data even when .gitattributes
      files are not found to prevent re-scanning for nonexistent files.
      Edward Thomson committed
  18. 05 Dec, 2014 1 commit
    • ignore: match git's rule negation rules · e05b2ff1
      A rule can only negate something which was explicitly mentioned in the
      rules before it. Change our parsing to ignore a negative rule which does
      not negate something mentioned in the rules above it.
      
      While here, fix a wrong allocator usage. The memory for the match string
      comes from pool allocator. We must not free it with the general
      allocator. We can instead simply forget the string and it will be
      cleaned up.
      Carlos Martín Nieto committed
  19. 17 Sep, 2014 1 commit
  20. 06 May, 2014 1 commit
    • Improve checks for ignore containment · f554611a
      The diff code was using an "ignored_prefix" directory to track if
      a parent directory was ignored that contained untracked files
      alongside tracked files. Unfortunately, when negative ignore rules
      were used for directories inside ignored parents, the wrong rules
      were applied to untracked files inside the negatively ignored
      child directories.
      
      This commit moves the logic for ignore containment into the workdir
      iterator (which is a better place for it), so the ignored-ness of
      a directory is contained in the frame stack during traversal.  This
      allows a child directory to override with a negative ignore and yet
      still restore the ignored state of the parent when we traverse out
      of the child.
      
      Along with this, there are some problems with "directory only"
      ignore rules on container directories.  Given "a/*" and "!a/b/c/"
      (where the second rule is a directory rule but the first rule is
      just a generic prefix rule), then the directory only constraint
      was having "a/b/c/d/file" match the first rule and not the second.
      This was fixed by having ignore directory-only rules test a rule
      against the prefix of a file with LEADINGDIR enabled.
      
      Lastly, spot checks for ignores using `git_ignore_path_is_ignored`
      were tested from the top directory down to the bottom to deal with
      the containment problem, but this is wrong. We have to test bottom
      to top so that negative subdirectory rules will be checked before
      parent ignore rules.
      
      This does change the behavior of some existing tests, but it seems
      only to bring us more in line with core Git, so I think those
      changes are acceptable.
      Russell Belfer committed
  21. 21 Apr, 2014 1 commit
  22. 18 Apr, 2014 1 commit
    • Pop ignore only if whole relative path matches · 6a0956e5
      When traversing the directory structure, the iterator pushes and
      pops ignore files using a vector.  Some directories don't have
      ignore files, so it uses a path comparison to decide when it is
      right to actually pop the last ignore file.  This was only
      comparing directory suffixes, though, so a subdirectory with the
      same name as a parent could result in the parent's .gitignore
      being popped off the list ignores too early.  This changes the
      logic to compare the entire relative path of the ignore file.
      Russell Belfer committed
  23. 17 Apr, 2014 6 commits
  24. 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
  25. 10 Apr, 2014 1 commit
    • Fix bug popping ignore files during wd iteration · 8f7bc646
      There were a couple bugs in popping ignore files during iteration
      that could result in incorrect decisions be made and thus ignore
      files below the root either not being loaded correctly or not
      being popped at the right time.
      
      One bug was an off-by-one in comparing the path of the gitignore
      file with the path being exited during iteration.
      
      The second bug was not correctly truncating the path being tracked
      during traversal if there were no ignores on the list (i.e. when
      you have no .gitignore at the root, but do have some in contained
      directories).
      Russell Belfer committed
  26. 11 Dec, 2013 2 commits
    • Remove converting user error to GIT_EUSER · 25e0b157
      This changes the behavior of callbacks so that the callback error
      code is not converted into GIT_EUSER and instead we propagate the
      return value through to the caller.  Instead of using the
      giterr_capture and giterr_restore functions, we now rely on all
      functions to pass back the return value from a callback.
      
      To avoid having a return value with no error message, the user
      can call the public giterr_set_str or some such function to set
      an error message.  There is a new helper 'giterr_set_callback'
      that functions can invoke after making a callback which ensures
      that some error message was set in case the callback did not set
      one.
      
      In places where the sign of the callback return value is
      meaningful (e.g. positive to skip, negative to abort), only the
      negative values are returned back to the caller, obviously, since
      the other values allow for continuing the loop.
      
      The hardest parts of this were in the checkout code where positive
      return values were overloaded as meaningful values for checkout.
      I fixed this by adding an output parameter to many of the internal
      checkout functions and removing the overload.  This added some
      code, but it is probably a better implementation.
      
      There is some funkiness in the network code where user provided
      callbacks could be returning a positive or a negative value and
      we want to rely on that to cancel the loop.  There are still a
      couple places where an user error might get turned into GIT_EUSER
      there, I think, though none exercised by the tests.
      Russell Belfer committed
    • Further EUSER and error propagation fixes · dab89f9b
      This continues auditing all the places where GIT_EUSER is being
      returned and making sure to clear any existing error using the
      new giterr_user_cancel helper.  As a result, places that relied
      on intercepting GIT_EUSER but having the old error preserved also
      needed to be cleaned up to correctly stash and then retrieve the
      actual error.
      
      Additionally, as I encountered places where error codes were not
      being propagated correctly, I tried to fix them up.  A number of
      those fixes are included in the this commit as well.
      Russell Belfer committed
  27. 28 Oct, 2013 1 commit
    • The "common.h" should be included before "config.h". · 157cef10
      When building libgit2 for ia32 architecture on a x64 machine, including
      "config.h" without a "common.h" would result the following error:
      C:\Program Files\Microsoft SDKs\Windows\v7.1\include\winbase.h(2288): error C2373: 'InterlockedIncrement' : redefinition; different type modifiers [C:\cygwin\home\zcbenz\codes\git-utils\build\libgit2.vcxproj]
      C:\Program Files\Microsoft SDKs\Windows\v7.1\include\winbase.h(2295): error C2373: 'InterlockedDecrement' : redefinition; different type modifiers [C:\cygwin\home\zcbenz\codes\git-utils\build\libgit2.vcxproj]
      C:\Program Files\Microsoft SDKs\Windows\v7.1\include\winbase.h(2303): error C2373: 'InterlockedExchange' : redefinition; different type modifiers [C:\cygwin\home\zcbenz\codes\git-utils\build\libgit2.vcxproj]
      C:\Program Files\Microsoft SDKs\Windows\v7.1\include\winbase.h(2314): error C2373: 'InterlockedExchangeAdd' : redefinition; different type modifiers [C:\cygwin\home\zcbenz\codes\git-utils\build\libgit2.vcxproj]
      Cheng Zhao committed
  28. 09 Aug, 2013 3 commits
    • Improve and comment git_ignore__pop_dir · 3bc3ed80
      This just cleans up the improved logic for popping ignore dirs
      and documents why the complex behavior is needed.
      Russell Belfer committed
    • Improve building ignore file lists · ba8b8c04
      The routines to push and pop ignore files while traversing a
      directory had some issues. In particular, setting up the initial
      list would sometimes push an ignore file before it ought to be
      applied if the starting path was a directory containing an ignore
      file. Also, the pop function was not always matching the right
      part of the path and would fail to pop ignores from the list in
      some cases.
      
      This adds some tests that exercise a particular problematic case
      and then fixes the problems that I could find related to this.
      
      At some point, I'd like to isolate this ignore rule management
      code and rewrite it, but that's a larger project and right now,
      I'll opt to just try to fix the broken behaviors.
      Russell Belfer committed
    • Revert PR #1462 and provide alternative fix · 4ba64794
      This rolls back the changes to fnmatch parsing from commit
      2e40a60e except for the tests
      that were added.  Instead this adds couple of new flags that can
      be passed in when attempting to parse an fnmatch pattern.  Also,
      this changes the pathspec match logic to special case matching a
      filename with a '!' prefix against a negative pattern.
      
      This fixes the build.
      Russell Belfer committed