This project is mirrored from https://github.com/git/git. Updated .
  1. 28 Jul, 2014 4 commits
    • Jeff King's avatar
      object_as_type: set commit index · 34dfe197
      Jeff King authored
      The point of the "index" field of struct commit is that
      every allocated commit would have one. It is supposed to be
      an invariant that whenever object->type is set to
      OBJ_COMMIT, we have a unique index.
      
      Commit 969eba63 (commit: push commit_index update into
      alloc_commit_node, 2014-06-10) covered this case for
      newly-allocated commits. However, we may also allocate an
      "unknown" object via lookup_unknown_object, and only later
      convert it to a commit. We must make sure that we set the
      commit index when we switch the type field.
      Signed-off-by: default avatarJeff King <peff@peff.net>
      Signed-off-by: default avatarJunio C Hamano <gitster@pobox.com>
      34dfe197
    • Jeff King's avatar
      add object_as_type helper for casting objects · c4ad00f8
      Jeff King authored
      When we call lookup_commit, lookup_tree, etc, the logic goes
      something like:
      
        1. Look for an existing object struct. If we don't have
           one, allocate and return a new one.
      
        2. Double check that any object we have is the expected
           type (and complain and return NULL otherwise).
      
        3. Convert an object with type OBJ_NONE (from a prior
           call to lookup_unknown_object) to the expected type.
      
      We can encapsulate steps 2 and 3 in a helper function which
      checks whether we have the expected object type, converts
      OBJ_NONE as appropriate, and returns the object.
      
      Not only does this shorten the code, but it also provides
      one central location for converting OBJ_NONE objects into
      objects of other types. Future patches will use that to
      enforce type-specific invariants.
      
      Since this is a refactoring, we would want it to behave
      exactly as the current code. It takes a little reasoning to
      see that this is the case:
      
        - for lookup_{commit,tree,etc} functions, we are just
          pulling steps 2 and 3 into a function that does the same
          thing.
      
        - for the call in peel_object, we currently only do step 3
          (but we want to consolidate it with the others, as
          mentioned above). However, step 2 is a noop here, as the
          surrounding conditional makes sure we have OBJ_NONE
          (which we want to keep to avoid an extraneous call to
          sha1_object_info).
      
        - for the call in lookup_commit_reference_gently, we are
          currently doing step 2 but not step 3. However, step 3
          is a noop here. The object we got will have just come
          from deref_tag, which must have figured out the type for
          each object in order to know when to stop peeling.
          Therefore the type will never be OBJ_NONE.
      Signed-off-by: default avatarJeff King <peff@peff.net>
      Signed-off-by: default avatarJunio C Hamano <gitster@pobox.com>
      c4ad00f8
    • Jeff King's avatar
      parse_object_buffer: do not set object type · fe0444b5
      Jeff King authored
      The only way that "obj" can be non-NULL is if it came from
      one of the lookup_* functions. These functions always ensure
      that the object has the expected type (and return NULL
      otherwise), so there is no need for us to set the type.
      Signed-off-by: default avatarJeff King <peff@peff.net>
      Signed-off-by: default avatarJunio C Hamano <gitster@pobox.com>
      fe0444b5
    • Jeff King's avatar
      move setting of object->type to alloc_* functions · fe24d396
      Jeff King authored
      The "struct object" type implements basic object
      polymorphism.  Individual instances are allocated as
      concrete types (or as a union type that can store any
      object), and a "struct object *" can be cast into its real
      type after examining its "type" enum.  This means it is
      dangerous to have a type field that does not match the
      allocation (e.g., setting the type field of a "struct blob"
      to "OBJ_COMMIT" would mean that a reader might read past the
      allocated memory).
      
      In most of the current code this is not a problem; the first
      thing we do after allocating an object is usually to set its
      type field by passing it to create_object. However, the
      virtual commits we create in merge-recursive.c do not ever
      get their type set. This does not seem to have caused
      problems in practice, though (presumably because we always
      pass around a "struct commit" pointer and never even look at
      the type).
      
      We can fix this oversight and also make it harder for future
      code to get it wrong by setting the type directly in the
      object allocation functions.
      
      This will also make it easier to fix problems with commit
      index allocation, as we know that any object allocated by
      alloc_commit_node will meet the invariant that an object
      with an OBJ_COMMIT type field will have a unique index
      number.
      Signed-off-by: default avatarJeff King <peff@peff.net>
      Signed-off-by: default avatarJunio C Hamano <gitster@pobox.com>
      fe24d396
  2. 14 Jul, 2014 4 commits
    • Jeff King's avatar
      object_as_type: set commit index · d66bebcb
      Jeff King authored
      The point of the "index" field of struct commit is that
      every allocated commit would have one. It is supposed to be
      an invariant that whenever object->type is set to
      OBJ_COMMIT, we have a unique index.
      
      Commit 969eba63 (commit: push commit_index update into
      alloc_commit_node, 2014-06-10) covered this case for
      newly-allocated commits. However, we may also allocate an
      "unknown" object via lookup_unknown_object, and only later
      convert it to a commit. We must make sure that we set the
      commit index when we switch the type field.
      Signed-off-by: default avatarJeff King <peff@peff.net>
      Signed-off-by: default avatarJunio C Hamano <gitster@pobox.com>
      d66bebcb
    • Jeff King's avatar
      add object_as_type helper for casting objects · 8ff226a9
      Jeff King authored
      When we call lookup_commit, lookup_tree, etc, the logic goes
      something like:
      
        1. Look for an existing object struct. If we don't have
           one, allocate and return a new one.
      
        2. Double check that any object we have is the expected
           type (and complain and return NULL otherwise).
      
        3. Convert an object with type OBJ_NONE (from a prior
           call to lookup_unknown_object) to the expected type.
      
      We can encapsulate steps 2 and 3 in a helper function which
      checks whether we have the expected object type, converts
      OBJ_NONE as appropriate, and returns the object.
      
      Not only does this shorten the code, but it also provides
      one central location for converting OBJ_NONE objects into
      objects of other types. Future patches will use that to
      enforce type-specific invariants.
      
      Since this is a refactoring, we would want it to behave
      exactly as the current code. It takes a little reasoning to
      see that this is the case:
      
        - for lookup_{commit,tree,etc} functions, we are just
          pulling steps 2 and 3 into a function that does the same
          thing.
      
        - for the call in peel_object, we currently only do step 3
          (but we want to consolidate it with the others, as
          mentioned above). However, step 2 is a noop here, as the
          surrounding conditional makes sure we have OBJ_NONE
          (which we want to keep to avoid an extraneous call to
          sha1_object_info).
      
        - for the call in lookup_commit_reference_gently, we are
          currently doing step 2 but not step 3. However, step 3
          is a noop here. The object we got will have just come
          from deref_tag, which must have figured out the type for
          each object in order to know when to stop peeling.
          Therefore the type will never be OBJ_NONE.
      Signed-off-by: default avatarJeff King <peff@peff.net>
      Signed-off-by: default avatarJunio C Hamano <gitster@pobox.com>
      8ff226a9
    • Jeff King's avatar
      parse_object_buffer: do not set object type · 5af01caa
      Jeff King authored
      The only way that "obj" can be non-NULL is if it came from
      one of the lookup_* functions. These functions always ensure
      that the object has the expected type (and return NULL
      otherwise), so there is no need for us to set the type.
      Signed-off-by: default avatarJeff King <peff@peff.net>
      Signed-off-by: default avatarJunio C Hamano <gitster@pobox.com>
      5af01caa
    • Jeff King's avatar
      move setting of object->type to alloc_* functions · d36f51c1
      Jeff King authored
      The "struct object" type implements basic object
      polymorphism.  Individual instances are allocated as
      concrete types (or as a union type that can store any
      object), and a "struct object *" can be cast into its real
      type after examining its "type" enum.  This means it is
      dangerous to have a type field that does not match the
      allocation (e.g., setting the type field of a "struct blob"
      to "OBJ_COMMIT" would mean that a reader might read past the
      allocated memory).
      
      In most of the current code this is not a problem; the first
      thing we do after allocating an object is usually to set its
      type field by passing it to create_object. However, the
      virtual commits we create in merge-recursive.c do not ever
      get their type set. This does not seem to have caused
      problems in practice, though (presumably because we always
      pass around a "struct commit" pointer and never even look at
      the type).
      
      We can fix this oversight and also make it harder for future
      code to get it wrong by setting the type directly in the
      object allocation functions.
      
      This will also make it easier to fix problems with commit
      index allocation, as we know that any object allocated by
      alloc_commit_node will meet the invariant that an object
      with an OBJ_COMMIT type field will have a unique index
      number.
      Signed-off-by: default avatarJeff King <peff@peff.net>
      Signed-off-by: default avatarJunio C Hamano <gitster@pobox.com>
      d36f51c1
  3. 07 Jul, 2014 1 commit
  4. 13 Jun, 2014 3 commits
    • Jeff King's avatar
      commit: record buffer length in cache · 8597ea3a
      Jeff King authored
      Most callsites which use the commit buffer try to use the
      cached version attached to the commit, rather than
      re-reading from disk. Unfortunately, that interface provides
      only a pointer to the NUL-terminated buffer, with no
      indication of the original length.
      
      For the most part, this doesn't matter. People do not put
      NULs in their commit messages, and the log code is happy to
      treat it all as a NUL-terminated string. However, some code
      paths do care. For example, when checking signatures, we
      want to be very careful that we verify all the bytes to
      avoid malicious trickery.
      
      This patch just adds an optional "size" out-pointer to
      get_commit_buffer and friends. The existing callers all pass
      NULL (there did not seem to be any obvious sites where we
      could avoid an immediate strlen() call, though perhaps with
      some further refactoring we could).
      Signed-off-by: default avatarJeff King <peff@peff.net>
      Signed-off-by: default avatarJunio C Hamano <gitster@pobox.com>
      8597ea3a
    • Jeff King's avatar
      use get_cached_commit_buffer where appropriate · a97934d8
      Jeff King authored
      Some call sites check commit->buffer to see whether we have
      a cached buffer, and if so, do some work with it. In the
      long run we may want to switch these code paths to make
      their decision on a different boolean flag (because checking
      the cache may get a little more expensive in the future).
      But for now, we can easily support them by converting the
      calls to use get_cached_commit_buffer.
      Signed-off-by: default avatarJeff King <peff@peff.net>
      Signed-off-by: default avatarJunio C Hamano <gitster@pobox.com>
      a97934d8
    • Jeff King's avatar
      provide a helper to set the commit buffer · 66c2827e
      Jeff King authored
      Right now this is just a one-liner, but abstracting it will
      make it easier to change later.
      Signed-off-by: default avatarJeff King <peff@peff.net>
      Signed-off-by: default avatarJunio C Hamano <gitster@pobox.com>
      66c2827e
  5. 28 Feb, 2014 1 commit
  6. 11 Sep, 2013 1 commit
  7. 18 Jul, 2013 1 commit
    • Stefan Beller's avatar
      parse_object_buffer: correct freeing the buffer · 8e92e8f2
      Stefan Beller authored
      If we exit early in the function parse_object_buffer, we did not
      write to *eaten_p. Then the calling function parse_object, which looks
      like the following with respect to the eaten variable, cannot rely on a
      proper value set in eaten, hence the freeing of the buffer depends
      on random values in memory.
      
      	struct object *parse_object(const unsigned char *sha1)
      	{
      		int eaten;
      		...
      		obj = parse_object_buffer(sha1, type, size, buffer, &eaten);
      		if (!eaten)
      			free(buffer);
      	}
      
      This change makes sure, the buffer freeing condition is deterministic.
      Signed-off-by: default avatarStefan Beller <stefanbeller@googlemail.com>
      Signed-off-by: default avatarJunio C Hamano <gitster@pobox.com>
      8e92e8f2
  8. 02 Jun, 2013 1 commit
    • Michael Haggerty's avatar
      object_array_entry: fix memory handling of the name field · 31faeb20
      Michael Haggerty authored
      Previously, the memory management of the object_array_entry::name
      field was inconsistent and undocumented.  object_array_entries are
      ultimately created by a single function, add_object_array_with_mode(),
      which has an argument "const char *name".  This function used to
      simply set the name field to reference the string pointed to by the
      name parameter, and nobody on the object_array side ever freed the
      memory.  Thus, it assumed that the memory for the name field would be
      managed by the caller, and that the lifetime of that string would be
      at least as long as the lifetime of the object_array_entry.  But
      callers were inconsistent:
      
      * Some passed pointers to constant strings or argv entries, which was
        OK.
      
      * Some passed pointers to newly-allocated memory, but didn't arrange
        for the memory ever to be freed.
      
      * Some passed the return value of sha1_to_hex(), which is a pointer to
        a statically-allocated buffer that can be overwritten at any time.
      
      * Some passed pointers to refnames that they received from a
        for_each_ref()-type iteration, but the lifetimes of such refnames is
        not guaranteed by the refs API.
      
      Bring consistency to this mess by changing object_array to make its
      own copy for the object_array_entry::name field and free this memory
      when an object_array_entry is deleted from the array.
      
      Many callers were passing the empty string as the name parameter, so
      as a performance optimization, treat the empty string specially.
      Instead of making a copy, store a pointer to a statically-allocated
      empty string to object_array_entry::name.  When deleting such an
      entry, skip the free().
      
      Change the callers that were already passing copies to
      add_object_array_with_mode() to either skip the copy, or (if the
      memory needed to be allocated anyway) freeing the memory itself.
      
      A part of this commit effectively reverts
      
          70d26c6e read_revisions_from_stdin: make copies for handle_revision_arg
      
      because the copying introduced by that commit (which is still
      necessary) is now done at a deeper level.
      Signed-off-by: default avatarMichael Haggerty <mhagger@alum.mit.edu>
      Signed-off-by: default avatarJunio C Hamano <gitster@pobox.com>
      31faeb20
  9. 28 May, 2013 2 commits
  10. 10 May, 2013 1 commit
  11. 02 May, 2013 1 commit
    • Jeff King's avatar
      lookup_object: prioritize recently found objects · 9a414486
      Jeff King authored
      The lookup_object function is backed by a hash table of all
      objects we have seen in the program. We manage collisions
      with a linear walk over the colliding entries, checking each
      with hashcmp(). The main cost of lookup is in these
      hashcmp() calls; finding our item in the first slot is
      cheaper than finding it in the second slot, which is cheaper
      than the third, and so on.
      
      If we assume that there is some locality to the object
      lookups (e.g., if X and Y collide, and we have just looked
      up X, the next lookup is more likely to be for X than for
      Y), then we can improve our average lookup speed by checking
      X before Y.
      
      This patch does so by swapping a found item to the front of
      the collision chain. The p0001 perf test reveals that this
      does indeed exploit locality in the case of "rev-list --all
      --objects":
      
      Test                               origin          this tree
      -------------------------------------------------------------------------
      0001.1: rev-list --all             0.40(0.38+0.02) 0.40(0.36+0.03) +0.0%
      0001.2: rev-list --all --objects   2.24(2.17+0.05) 1.86(1.79+0.05) -17.0%
      
      This is not surprising, as the full object traversal will
      hit the same tree entries over and over (e.g., for every
      commit that doesn't change "Documentation/", we will have to
      look up the same sha1 just to find out that we already
      processed it).
      
      The reason why this technique works (and does not violate
      any properties of the hash table) is subtle and bears some
      explanation. Let's imagine we get a lookup for sha1 `X`, and
      it hashes to bucket `i` in our table. That stretch of the
      table may look like:
      
      index       | i-1 |  i  | i+1 | i+2 |
             -----------------------------------
      entry   ... |  A  |  B  |  C  |  X  | ...
             -----------------------------------
      
      We start our probe at i, see that B does not match, nor does
      C, and finally find X. There may be multiple C's in the
      middle, but we know that there are no empty slots (or else
      we would not find X at all).
      
      We do not know the original index of B; it may be `i`, or it
      may be less than i (e.g., if it were `i-1`, it would collide
      with A and spill over into the `i` bucket). So it is
      acceptable for us to move it to the right of a contiguous
      stretch of entries (because we will find it from a linear
      walk starting anywhere at `i` or before), but never to the
      left (if we moved it to `i-1`, we would miss it when
      starting our walk at `i`).
      
      We do know the original index of X; it is `i`, so it is safe
      to place it anywhere in the contiguous stretch between `i`
      and where we found it (`i+2` in the this case).
      
      This patch does a pure swap; after finding X in the
      situation above, we would end with:
      
      index       | i-1 |  i  | i+1 | i+2 |
             -----------------------------------
      entry   ... |  A  |  X  |  C  |  B  | ...
             -----------------------------------
      
      We could instead bump X into the `i` slot, and then shift
      the whole contiguous chain down by one, resulting in:
      
      index       | i-1 |  i  | i+1 | i+2 |
             -----------------------------------
      entry   ... |  A  |  X  |  B  |  C  | ...
             -----------------------------------
      
      That puts our chain in true most-recently-used order.
      However, experiments show that it is not any faster (and in
      fact, is slightly slower due to the extra manipulation).
      Signed-off-by: default avatarJeff King <peff@peff.net>
      Signed-off-by: default avatarJunio C Hamano <gitster@pobox.com>
      9a414486
  12. 17 Mar, 2013 1 commit
    • Jeff King's avatar
      avoid segfaults on parse_object failure · 75a95490
      Jeff King authored
      Many call-sites of parse_object assume that they will get a
      non-NULL return value; this is not the case if we encounter
      an error while parsing the object.
      
      This patch adds a wrapper function around parse_object that
      handles dying automatically, and uses it anywhere we
      immediately try to access the return value as a non-NULL
      pointer (i.e., anywhere that we would currently segfault).
      
      This wrapper may also be useful in other places. The most
      obvious one is code like:
      
        o = parse_object(sha1);
        if (!o)
      	  die(...);
      
      However, these should not be mechanically converted to
      parse_object_or_die, as the die message is sometimes
      customized. Later patches can address these sites on a
      case-by-case basis.
      Signed-off-by: default avatarJeff King <peff@peff.net>
      Signed-off-by: default avatarJunio C Hamano <gitster@pobox.com>
      75a95490
  13. 30 Apr, 2012 1 commit
  14. 30 Mar, 2012 1 commit
  15. 07 Mar, 2012 1 commit
    • Duy Nguyen's avatar
      parse_object: avoid putting whole blob in core · 090ea126
      Duy Nguyen authored
      Traditionally, all the callers of check_sha1_signature() first
      called read_sha1_file() to prepare the whole object data in core,
      and called this function.  The function is used to revalidate what
      we read from the object database actually matches the object name we
      used to ask for the data from the object database.
      
      Update the API to allow callers to pass NULL as the object data, and
      have the function read and hash the object data using streaming API
      to recompute the object name, without having to hold everything in
      core at the same time.  This is most useful in parse_object() that
      parses a blob object, because this caller does not have to keep the
      actual blob data around in memory after a "struct blob" is returned.
      Signed-off-by: Duy Nguyen's avatarNguyễn Thái Ngọc Duy <pclouds@gmail.com>
      Signed-off-by: default avatarJunio C Hamano <gitster@pobox.com>
      090ea126
  16. 05 Jan, 2012 1 commit
    • Jeff King's avatar
      parse_object: try internal cache before reading object db · ccdc6037
      Jeff King authored
      When parse_object is called, we do the following:
      
        1. read the object data into a buffer via read_sha1_file
      
        2. call parse_object_buffer, which then:
      
           a. calls the appropriate lookup_{commit,tree,blob,tag}
      	to either create a new "struct object", or to find
      	an existing one. We know the appropriate type from
      	the lookup in step 1.
      
           b. calls the appropriate parse_{commit,tree,blob,tag}
              to parse the buffer for the new (or existing) object
      
      In step 2b, all of the called functions are no-ops for
      object "X" if "X->object.parsed" is set. I.e., when we have
      already parsed an object, we end up going to a lot of work
      just to find out at a low level that there is nothing left
      for us to do (and we throw away the data from read_sha1_file
      unread).
      
      We can optimize this by moving the check for "do we have an
      in-memory object" from 2a before the expensive call to
      read_sha1_file in step 1.
      
      This might seem circular, since step 2a uses the type
      information determined in step 1 to call the appropriate
      lookup function. However, we can notice that all of the
      lookup_* functions are backed by lookup_object. In other
      words, all of the objects are kept in a master hash table,
      and we don't actually need the type to do the "do we have
      it" part of the lookup, only to do the "and create it if it
      doesn't exist" part.
      
      This can save time whenever we call parse_object on the same
      sha1 twice in a single program. Some code paths already
      perform this optimization manually, with either:
      
        if (!obj->parsed)
      	  obj = parse_object(obj->sha1);
      
      if you already have a "struct object", or:
      
        struct object *obj = lookup_unknown_object(sha1);
        if (!obj || !obj->parsed)
      	  obj = parse_object(sha1);
      
      if you don't.  This patch moves the optimization into
      parse_object itself.
      
      Most git operations won't notice any impact. Either they
      don't parse a lot of duplicate sha1s, or the calling code
      takes special care not to re-parse objects. I timed two
      code paths that do benefit (there may be more, but these two
      were immediately obvious and easy to time).
      
      The first is fast-export, which calls parse_object on each
      object it outputs, like this:
      
        object = parse_object(sha1);
        if (!object)
      	  die(...);
        if (object->flags & SHOWN)
      	  return;
      
      which means that just to realize we have already shown an
      object, we will read the whole object from disk!
      
      With this patch, my best-of-five time for "fast-export --all" on
      git.git dropped from 26.3s to 21.3s.
      
      The second case is upload-pack, which will call parse_object
      for each advertised ref (because it needs to peel tags to
      show "^{}" entries). This doesn't matter for most
      repositories, because they don't have a lot of refs pointing
      to the same objects. However, if you have a big alternates
      repository with a shared object db for a number of child
      repositories, then the alternates repository will have
      duplicated refs representing each of its children.
      
      For example, GitHub's alternates repository for git.git has
      ~120,000 refs, of which only ~3200 are unique. The time for
      upload-pack to print its list of advertised refs dropped
      from 3.4s to 0.76s.
      Signed-off-by: default avatarJeff King <peff@peff.net>
      Signed-off-by: default avatarJunio C Hamano <gitster@pobox.com>
      ccdc6037
  17. 17 Nov, 2011 1 commit
  18. 15 May, 2011 1 commit
  19. 06 Sep, 2010 1 commit
  20. 04 Sep, 2010 1 commit
    • Duy Nguyen's avatar
      parse_object: pass on the original sha1, not the replaced one · 2e3400c0
      Duy Nguyen authored
      Commit 0e87c367 (object: call "check_sha1_signature" with the
      replacement sha1) changed the first argument passed to
      parse_object_buffer() from "sha1" to "repl". With that change,
      the returned obj pointer has the replacement SHA1 in obj->sha1,
      not the original one.
      
      But when using lookup_commit() and then parse_commit() on a
      commit, we get an object pointer with the original sha1, but
      the commit content comes from the replacement commit.
      
      So the result we get from using parse_object() is different
      from the we get from using lookup_commit() followed by
      parse_commit().
      
      It looks much simpler and safer to fix this inconsistency by
      passing "sha1" to parse_object_bufer() instead of "repl".
      
      The commit comment should be used to tell the the replacement
      commit is replacing another commit and why. So it should be
      easy to see that we have a replacement commit instead of an
      original one.
      
      And it is not a problem if the content of the commit is not
      consistent with the sha1 as cat-file piped to hash-object can
      be used to see the difference.
      Signed-off-by: Christian Couder's avatarChristian Couder <chriscool@tuxfamily.org>
      Signed-off-by: default avatarJunio C Hamano <gitster@pobox.com>
      2e3400c0
  21. 20 Apr, 2010 1 commit
    • Jonathan Nieder's avatar
      fix "bundle --stdin" segfault · 97a20eea
      Jonathan Nieder authored
      When passed an empty list, objects_array_remove_duplicates() corrupts it
      by changing the number of entries from 0 to 1.
      
      The problem lies in the condition of its main loop:
      
      	for (ref = 0; ref < array->nr - 1; ref++) {
      
      The loop body manipulates the supplied object array.  In the case of an
      empty array, it should not be doing anything at all.  But array->nr is an
      unsigned quantity, so the code enters the loop, in particular increasing
      array->nr.  Fix this by comparing (ref + 1 < array->nr) instead.
      
      This bug can be triggered by git bundle --stdin:
      
      	$ echo HEAD | git bundle create some.bundle --stdin’
      	Segmentation fault (core dumped)
      
      The list of commits to bundle appears to be empty because of another bug:
      by the time the revision-walking machinery gets to look at it, standard
      input has already been consumed by rev-list, so this function gets an
      empty list of revisions.
      
      After this patch, git bundle --stdin still does not work; it just doesn’t
      segfault any more.
      Reported-by: default avatarJoey Hess <joey@kitenet.net>
      Signed-off-by: default avatarJonathan Nieder <jrnieder@gmail.com>
      Signed-off-by: default avatarJunio C Hamano <gitster@pobox.com>
      97a20eea
  22. 18 Jan, 2010 1 commit
  23. 01 Jun, 2009 1 commit
  24. 20 May, 2009 1 commit
  25. 17 May, 2009 1 commit
  26. 18 Jan, 2009 1 commit
  27. 04 Feb, 2008 1 commit
  28. 22 Dec, 2007 1 commit
  29. 06 Jun, 2007 1 commit
  30. 25 May, 2007 1 commit
  31. 24 Apr, 2007 1 commit