1. 14 Apr, 2021 1 commit
  2. 05 Jan, 2021 1 commit
  3. 19 Dec, 2020 1 commit
  4. 27 Nov, 2020 1 commit
  5. 11 Oct, 2020 1 commit
  6. 05 Jun, 2020 1 commit
  7. 11 May, 2020 3 commits
    • assert: allow non-int returning functions to assert · cbae1c21
      Include GIT_ASSERT_WITH_RETVAL and GIT_ASSERT_ARG_WITH_RETVAL so that
      functions that do not return int (or more precisely, where `-1` would
      not be an error code) can assert.
      
      This allows functions that return, eg, NULL on an error code to do that
      by passing the return value (in this example, `NULL`) as a second
      parameter to the GIT_ASSERT_WITH_RETVAL functions.
      Edward Thomson committed
    • assert: optionally fall-back to assert(3) · a95096ba
      Fall back to the system assert(3) in debug builds, which may aide
      in debugging.
      
      "Safe" assertions can be enabled in debug builds by setting
      GIT_ASSERT_HARD=0.  Similarly, hard assertions can be enabled in
      release builds by setting GIT_ASSERT_HARD to nonzero.
      Edward Thomson committed
    • Introduce GIT_ASSERT macros · abe2efe1
      Provide macros to replace usages of `assert`.  A true `assert` is
      punishing as a library.  Instead we should do our best to not crash.
      
      GIT_ASSERT_ARG(x) will now assert that the given argument complies to
      some format and sets an error message and returns `-1` if it does not.
      
      GIT_ASSERT(x) is for internal usage, and available as an internal
      consistency check.  It will set an error message and return `-1` in the
      event of failure.
      Edward Thomson committed
  8. 10 Mar, 2020 1 commit
  9. 10 Jan, 2020 1 commit
    • win32: fix relative symlinks pointing into dirs · 7d55bee6
      On Windows platforms, we need some logic to emulate symlink(3P) defined
      by POSIX. As unprivileged symlinks on Windows are a rather new feature,
      our current implementation is comparatively new and still has some
      rough edges in special cases.
      
      One such case is relative symlinks. While relative symlinks to files in
      the same directory work as expected, libgit2 currently fails to create
      reltaive symlinks pointing into other directories. This is due to the
      fact that we forgot to translate the Unix-style target path to
      Windows-style. Most importantly, we are currently not converting
      directory separators from "/" to "\".
      
      Fix the issue by calling `git_win32_path_canonicalize` on the target.
      Add a test that verifies our ability to create such relative links
      across directories.
      Patrick Steinhardt committed
  10. 25 Nov, 2019 1 commit
  11. 21 Sep, 2019 4 commits
    • posix: remove superseded POSIX regex wrappers · f585b129
      The old POSIX regex wrappers have been superseded by our own regexp API
      that provides a higher-level abstraction. Remove the POSIX wrappers in
      favor of the new one.
      Patrick Steinhardt committed
    • regexp: implement new regular expression API · d77378eb
      We currently support a set of different regular expression backends with
      PCRE, PCRE2, regcomp(3P) and regcomp_l(3). The current implementation of
      this is done via a simple POSIX wrapper that either directly uses
      supplied functions or that is a very small wrapper.
      
      To support PCRE and PCRE2, we use their provided <pcreposix.h> and
      <pcre2posix.h> wrappers. These wrappers are implemented in such a way
      that the accompanying libraries pcre-posix and pcre2-posix provide the
      same symbols as the libc ones, namely regcomp(3P) et al. This works out
      on some systems just fine, most importantly on glibc-based ones, where
      the regular expression functions are implemented as weak aliases and
      thus get overridden by linking in the pcre{,2}-posix library. On other
      systems we depend on the linking order of libc and pcre library, and as
      libc always comes first we will end up with the functions of the libc
      implementation. As a result, we may use the structures `regex_t` and
      `regmatch_t` declared by <pcre{,2}posix.h>, but use functions defined by
      the libc, leading to segfaults.
      
      The issue is not easily solvable. Somed distributions like Debian have
      resolved this by patching PCRE and PCRE2 to carry custom prefixes to all
      the POSIX function wrappers. But this is not supported by upstream and
      thus inherently unportable between distributions. We could instead try
      to modify linking order, but this starts becoming fragile and will not
      work e.g. when libgit2 is loaded via dlopen(3P) or similar ways. In the
      end, this means that we simply cannot use the POSIX wrappers provided by
      the PCRE libraries at all.
      
      Thus, this commit introduces a new regular expression API. The new API
      is on a tad higher level than the previous POSIX abstraction layer, as
      it tries to abstract away any non-portable flags like e.g. REG_EXTENDED,
      which has no equivalents in all of our supported backends. As there are
      no users of POSIX regular expressions that do _not_ reguest REG_EXTENDED
      this is fine to be abstracted away, though. Due to the API being
      higher-level than before, it should generally be a tad easier to use
      than the previous one.
      
      Note: ideally, the new API would've been called `git_regex_foobar` with
      a file "regex.h" and "regex.c". Unfortunately, this is currently
      impossible to implement due to naming clashes between the then-existing
      "regex.h" and <regex.h> provided by the libc. As we add the source
      directory of libgit2 to the header search path, an include of <regex.h>
      would always find our own "regex.h". Thus, we have to take the bitter
      pill of adding one more character to all the functions to disambiguate
      the includes.
      
      To improve guarantees around cross-backend compatibility, this commit
      also brings along an improved regular expression test suite
      core::regexp.
      Patrick Steinhardt committed
    • buffer: fix printing into out-of-memory buffer · 174b7a32
      Before printing into a `git_buf` structure, we always call `ENSURE_SIZE`
      first. This macro will reallocate the buffer as-needed depending on
      whether the current amount of allocated bytes is sufficient or not. If
      `asize` is big enough, then it will just do nothing, otherwise it will
      call out to `git_buf_try_grow`. But in fact, it is insufficient to only
      check `asize`.
      
      When we fail to allocate any more bytes e.g. via `git_buf_try_grow`,
      then we set the buffer's pointer to `git_buf__oom`. Note that we touch
      neither `asize` nor `size`. So if we just check `asize > targetsize`,
      then we will happily let the caller of `ENSURE_SIZE` proceed with an
      out-of-memory buffer. As a result, we will print all bytes into the
      out-of-memory buffer instead, resulting in an out-of-bounds write.
      
      Fix the issue by having `ENSURE_SIZE` verify that the buffer is not
      marked as OOM. Add a test to verify that we're not writing into the OOM
      buffer.
      Patrick Steinhardt committed
    • buffer: fix infinite loop when growing buffers · 208f1d7a
      When growing buffers, we repeatedly multiply the currently allocated
      number of bytes by 1.5 until it exceeds the requested number of bytes.
      This has two major problems:
      
          1. If the current number of bytes is tiny and one wishes to resize
             to a comparatively huge number of bytes, then we may need to loop
             thousands of times.
      
          2. If resizing to a value close to `SIZE_MAX` (which would fail
             anyway), then we probably hit an infinite loop as multiplying the
             current amount of bytes will repeatedly result in integer
             overflows.
      
      When reallocating buffers, one typically chooses values close to 1.5 to
      enable re-use of resulting memory holes in later reallocations. But
      because of this, it really only makes sense to use a factor of 1.5
      _once_, but not looping until we finally are able to fit it. Thus, we
      can completely avoid the loop and just opt for the much simpler
      algorithm of multiplying with 1.5 once and, if the result doesn't fit,
      just use the target size. This avoids both problems of looping
      extensively and hitting overflows.
      
      This commit also adds a test that would've previously resulted in an
      infinite loop.
      Patrick Steinhardt committed
  12. 23 Aug, 2019 1 commit
    • util: do not perform allocations in insertsort · 8cbef12d
      Our hand-rolled fallback sorting function `git__insertsort_r` does an
      in-place sort of the given array. As elements may not necessarily be
      pointers, it needs a way of swapping two values of arbitrary size, which
      is currently implemented by allocating a temporary buffer of the
      element's size. This is problematic, though, as the emulated `qsort`
      interface doesn't provide any return values and thus cannot signal an
      error if allocation of that temporary buffer has failed.
      
      Convert the function to swap via a temporary buffer allocated on the
      stack. Like this, it can `memcpy` contents of both elements in small
      batches without requiring a heap allocation. The buffer size has been
      chosen such that in most cases, a single iteration of copying will
      suffice. Most importantly, it can fully contain `git_oid` structures and
      pointers.
      
      Add a bunch of tests for the `git__qsort_r` interface to verify nothing
      breaks. Furthermore, this removes the declaration of `git__insertsort_r`
      and makes it static as it is not used anywhere else.
      Patrick Steinhardt committed
  13. 20 Jul, 2019 4 commits
    • win32: fix symlinks to relative file targets · 50194dcd
      When creating a symlink in Windows, one needs to tell Windows whether
      the symlink should be a file or directory symlink. To determine which
      flag to pass, we call `GetFileAttributesW` on the target file to see
      whether it is a directory and then pass the flag accordingly. The
      problem though is if create a symlink with a relative target path, then
      we will check that relative path while not necessarily being inside of
      the working directory where the symlink is to be created. Thus, getting
      its attributes will either fail or return attributes of the wrong
      target.
      
      Fix this by resolving the target path relative to the directory in which
      the symlink is to be created.
      Patrick Steinhardt committed
    • tests: core: improve symlink test coverage · 93d37a1d
      Add two more tests to verify that we're not deleting symlink targets,
      but the symlinks themselves. Furthermore, convert several `cl_skip`s on
      Win32 to conditional skips depending on whether the clar sandbox
      supports symlinks or not. Windows is grown up now and may allow
      unprivileged symlinks if the machine has been configured accordingly.
      Patrick Steinhardt committed
    • tests: core: add missing asserts for several function calls · 683ea2b0
      Several function calls to `p_stat` and `p_close` have no verification if
      they actually succeeded. As these functions _may_ fail and as we also
      want to make sure that we're not doing anything dumb, let's check them,
      too.
      Patrick Steinhardt committed
    • fileops: rename to "futils.h" to match function signatures · e54343a4
      Our file utils functions all have a "futils" prefix, e.g.
      `git_futils_touch`. One would thus naturally guess that their
      definitions and implementation would live in files "futils.h" and
      "futils.c", respectively, but in fact they live in "fileops.h".
      
      Rename the files to match expectations.
      Patrick Steinhardt committed
  14. 24 Jun, 2019 1 commit
    • win32: cast WinAPI to void * before casting · c512d58f
      GetProcAddress is prototyped to return a `FARPROC`, which is meant to be
      a generic function pointer.  It's literally `int (FAR WINAPI * FARPROC)()`
      which gcc complains if you attempt to cast to a `void (*)(GIT_SRWLOCK *)`.
      Cast to a `void *` before casting to avoid warnings about the arguments.
      Edward Thomson committed
  15. 15 Jun, 2019 1 commit
    • wildmatch: import wildmatch from git.git · a9f57629
      In commit 70a8fc999d (stop using fnmatch (either native or
      compat), 2014-02-15), upstream git has switched over all code
      from their internal fnmatch copy to its new wildmatch code. We
      haven't followed suit, and thus have developed some
      incompatibilities in how we match regular expressions.
      
      Import git's wildmatch from v2.22.0 and add a test suite based on
      their t3070-wildmatch.sh tests.
      Patrick Steinhardt committed
  16. 14 Jun, 2019 3 commits
    • posix: remove `p_fallocate` abstraction · 2d85c7e8
      By now, we have repeatedly failed to provide a nice
      cross-platform implementation of `p_fallocate`. Recent tries to
      do that escalated quite fast to a set of different CMake checks,
      implementations, fallbacks, etc., which started to look real
      awkward to maintain. In fact, `p_fallocate` had only been
      introduced in commit 4e3949b7 (tests: test that largefiles can
      be read through the tree API, 2019-01-30) to support a test with
      large files, but given the maintenance costs it just seems not to
      be worht it.
      
      As we have removed the sole user of `p_fallocate` in the previous
      commit, let's drop it altogether.
      Patrick Steinhardt committed
    • Rename opt init functions to `options_init` · 0b5ba0d7
      In libgit2 nomenclature, when we need to verb a direct object, we name
      a function `git_directobject_verb`.  Thus, if we need to init an options
      structure named `git_foo_options`, then the name of the function that
      does that should be `git_foo_options_init`.
      
      The previous names of `git_foo_init_options` is close - it _sounds_ as
      if it's initializing the options of a `foo`, but in fact
      `git_foo_options` is its own noun that should be respected.
      
      Deprecate the old names; they'll now call directly to the new ones.
      Edward Thomson committed
  17. 19 May, 2019 8 commits
  18. 22 Feb, 2019 1 commit
  19. 15 Feb, 2019 5 commits
    • oidmap: remove legacy low-level interface · bd66925a
      Remove the low-level interface that was exposing implementation details of
      `git_oidmap` to callers. From now on, only the high-level functions shall be
      used to retrieve or modify values of a map. Adjust remaining existing callers.
      Patrick Steinhardt committed
    • strmap: remove legacy low-level interface · fdfabdc4
      Remove the low-level interface that was exposing implementation details of
      `git_strmap` to callers. From now on, only the high-level functions shall be
      used to retrieve or modify values of a map. Adjust remaining existing callers.
      Patrick Steinhardt committed
    • maps: provide high-level iteration interface · 18cf5698
      Currently, our headers need to leak some implementation details of maps due to
      their direct use of indices in the implementation of their foreach macros. This
      makes it impossible to completely hide the map structures away, and also makes
      it impossible to include the khash implementation header in the C files of the
      respective map only.
      
      This is now being fixed by providing a high-level iteration interface
      `map_iterate`, which takes as inputs the map that shall be iterated over, an
      iterator as well as the locations where keys and values shall be put into. For
      simplicity's sake, the iterator is a simple `size_t` that shall initialized to
      `0` on the first call. All existing foreach macros are then adjusted to make use
      of this new function.
      Patrick Steinhardt committed
    • oidmap: introduce high-level setter for key/value pairs · 2e0a3048
      Currently, one would use either `git_oidmap_insert` to insert key/value pairs
      into a map or `git_oidmap_put` to insert a key only. These function have
      historically been macros, which is why their syntax is kind of weird: instead of
      returning an error code directly, they instead have to be passed a pointer to
      where the return value shall be stored. This does not match libgit2's common
      idiom of directly returning error codes.Furthermore, `git_oidmap_put` is tightly
      coupled with implementation details of the map as it exposes the index of
      inserted entries.
      
      Introduce a new function `git_oidmap_set`, which takes as parameters the map,
      key and value and directly returns an error code. Convert all trivial callers of
      `git_oidmap_insert` and `git_oidmap_put` to make use of it.
      Patrick Steinhardt committed
    • oidmap: introduce high-level getter for values · 9694ef20
      The current way of looking up an entry from a map is tightly coupled with the
      map implementation, as one first has to look up the index of the key and then
      retrieve the associated value by using the index. As a caller, you usually do
      not care about any indices at all, though, so this is more complicated than
      really necessary. Furthermore, it invites for errors to happen if the correct
      error checking sequence is not being followed.
      
      Introduce a new high-level function `git_oidmap_get` that takes a map and a key
      and returns a pointer to the associated value if such a key exists. Otherwise,
      a `NULL` pointer is returned. Adjust all callers that can trivially be
      converted.
      Patrick Steinhardt committed