1. 09 Jul, 2017 3 commits
    • Jeff King's avatar
      reflog-walk: apply --since/--until to reflog dates · de239446
      Jeff King authored
      When doing a reflog walk, we use the commit's date to
      do any date limiting. In earlier versions of Git, this could
      lead to nonsense results, since a skipped commit would
      truncate the traversal. So a sequence like:
        git commit ...
        git checkout week-old-branch
        git checkout -
        git log -g --since=1.day.ago
      would stop at the week-old-branch, even though the "git
      commit" entry further back is still interesting.
      As of the prior commit, which uses a parent-less traversal
      of the reflog, you get the whole reflog minus any commits
      whose dates do not match the specified options. This is
      arguably useful, as you could scan the reflogs for commits
      that originated in a certain range.
      But more likely a user doing a reflog walk wants to limit
      based on the reflog entries themselves. You can simulate
      --until with:
        git log -g @{1.day.ago}
      but there's no way to ask Git to traverse only back to a
      certain date. E.g.:
        # show me reflog entries from the past day
        git log -g --since=1.day.ago
      This patch teaches the revision machinery to prefer the
      reflog entry dates to the commit dates when doing a reflog
      walk. Technically this is a change in behavior that affects
      plumbing, but the previous behavior was so buggy that it's
      unlikely anyone was relying on it.
      Signed-off-by: default avatarJeff King <[email protected]>
      Signed-off-by: default avatarJunio C Hamano <[email protected]>
    • Jeff King's avatar
      reflog-walk: stop using fake parents · d08565bf
      Jeff King authored
      The reflog-walk system works by putting a ref's tip into the
      pending queue, and then "traversing" the reflog by
      pretending that the parent of each commit is the previous
      reflog entry.
      This causes a number of user-visible oddities, as documented
      in t1414 (and the commit message which introduced it). We
      can fix all of them in one go by replacing the fake-reflog
      system with a much simpler one: just keeping a list of
      reflogs to show, and walking through them entry by entry.
      The implementation is fairly straight-forward, but there are
      a few items to note:
        1. We obviously must skip calling add_parents_to_list()
           when we are traversing reflogs, since we do not want to
           walk the original parents at all.  As a result, we must call
           try_to_simplify_commit() ourselves.
           There are other parts of add_parents_to_list() we skip,
           as well, but none of them should matter for a reflog
             -  We do not allow UNINTERESTING commits, nor
                symmetric ranges (and we bail when these are used
                with "-g").
             - Using --source makes no sense, since we aren't
               traversing. The reflog selector shows the same
               information with more detail.
             - Using --first-parent is still sensible, since you
               may want to see the first-parent diff for each
               entry. But since we're not traversing, we don't
               need to cull the parent list here.
        2. Since we now just walk the reflog entries themselves,
           rather than starting with the ref tip, we now look at
           the "new" field of each entry rather than the "old"
           (i.e., we are showing entries, not faking parents).
           This removes all of the tricky logic around skipping
           past root commits.
           But note that we have no way to show an entry with the
           null sha1 in its "new" field (because such a commit
           obviously does not exist). Normally this would not
           happen, since we delete reflogs along with refs, but
           there is one special case. When we rename the currently
           checked out branch, we write two reflog entries into
           the HEAD log: one where the commit goes away, and
           another where it comes back.
           Prior to this commit, we show both entries with
           identical reflog messages. After this commit, we show
           only the "comes back" entry. See the update in t3200
           which demonstrates this.
           Arguably either is fine, as the whole double-entry
           thing is a bit hacky in the first place. And until a
           recent fix, we truncated the traversal in such a case
           anyway, which was _definitely_ wrong.
        3. We show individual reflogs in order, but choose which
           reflog to show at each stage based on which has the
           most recent timestamp.  This interleaves the output
           from multiple reflogs based on date order, which is
           probably what you'd want with limiting like "-n 30".
           Note that the implementation aims for simplicity. It
           does a linear walk over the reflog queue for each
           commit it pulls, which may perform badly if you
           interleave an enormous number of reflogs. That seems
           like an unlikely use case; if we did want to handle it,
           we could probably keep a priority queue of reflogs,
           ordered by the timestamp of their current tip entry.
      Signed-off-by: default avatarJeff King <[email protected]>
      Signed-off-by: default avatarJunio C Hamano <[email protected]>
    • Jeff King's avatar
      rev-list: check reflog_info before showing usage · 7f97de5e
      Jeff King authored
      When git-rev-list sees no pending commits, it shows a usage
      message. This works even when reflog-walking is requested,
      because the reflog-walk code currently puts the reflog tips
      into the pending queue.
      In preparation for refactoring the reflog-walk code, let's
      explicitly check whether we have any reflogs to walk. For
      now this is a noop, but the existing reflog tests will make
      sure that it kicks in after the refactoring. Likewise, we'll
      add a test that "rev-list -g" without specifying any reflogs
      continues to fail (so that we know our check does not kick
      in too aggressively).
      Note that the implementation needs to go into its own
      sub-function, as the walk code does not expose its innards
      outside of reflog-walk.c.
      Signed-off-by: default avatarJeff King <[email protected]>
      Signed-off-by: default avatarJunio C Hamano <[email protected]>
  2. 07 Jul, 2017 3 commits
    • Jeff King's avatar
      reflog-walk: include all fields when freeing complete_reflogs · e30d463d
      Jeff King authored
      When we encounter an error adding reflogs for a walk, we try
      to free any logs we have read. But we didn't free all
      fields, meaning that we could in theory leak all of the
      "items" array (which would consitute the bulk of the
      allocated memory).
      This patch adds a helper which frees all of the entries and
      uses it as appropriate.
      As it turns out, the leak seems impossible to trigger with
      the current code. Of the three error paths that free the
      complete_reflogs struct, two only kick in when the items
      array is empty, and the third was removed entirely in the
      previous commit.
      So this patch should be a noop in terms of behavior, but it
      fixes a potential maintenance headache should anybody add a
      new error path and copy the partial-free code. Which is
      what happened in 5026b471 (add_reflog_for_walk: avoid
      memory leak, 2017-05-04), though its leaky call was the
      third one that was recently removed.
      Signed-off-by: default avatarJeff King <[email protected]>
      Signed-off-by: default avatarJunio C Hamano <[email protected]>
    • Jeff King's avatar
      reflog-walk: don't free reflogs added to cache · 8aae3cf7
      Jeff King authored
      The add_reflog_for_walk() function keeps a cache mapping
      refnames to their reflog contents. We use a cached reflog
      entry if available, and otherwise allocate and store a new
      Since 5026b471 (add_reflog_for_walk: avoid memory leak,
      2017-05-04), when we hit an error parsing a date-based
      reflog spec, we free the reflog memory but leave the cache
      entry pointing to the now-freed memory.
      We can fix this by just leaving the memory intact once it
      has made it into the cache. This may leave an unused entry
      in the cache, but that's OK. And it means we also catch a
      similar situation: we may not have allocated at all in this
      invocation, but simply be pointing to a cached entry from a
      previous invocation (which is relying on that entry being
      The new test in t1411 exercises this case and fails when run
      with --valgrind or ASan.
      Signed-off-by: default avatarJeff King <[email protected]>
      Signed-off-by: default avatarJunio C Hamano <[email protected]>
    • Jeff King's avatar
      reflog-walk: duplicate strings in complete_reflogs list · 75afe7ac
      Jeff King authored
      As part of the add_reflog_to_walk() function, we keep a
      string_list mapping refnames to their reflog contents. This
      serves as a cache so that accessing the same reflog twice
      requires only a single copy of the log in memory.
      The string_list is initialized via xcalloc, meaning its
      strdup_strings field is set to 0. But after inserting a
      string into the list, we unconditionally call free() on the
      string, leaving the list pointing to freed memory. If
      another reflog is added (e.g., "git log -g HEAD HEAD"), then
      the second one may have unpredictable results.
      The extra free was added by 5026b471 (add_reflog_for_walk:
      avoid memory leak, 2017-05-04). Though if you look
      carefully, you can see that the code was buggy even before
      then. If we tried to read the reflogs by time but came up
      with no entries, we exited with an error, freeing the string
      in that code path. So the bug was harder to trigger, but
      still there.
      We can fix it by just asking the string list to make a copy
      of the string. Technically we could fix the problem by not
      calling free() on our string (and just handing over
      ownership to the string list), but there are enough
      conditionals that it's quite hard to figure out which code
      paths need the free and which do not. Simpler is better
      The new test reliably shows the problem when run with
      --valgrind or ASAN.
      Signed-off-by: default avatarJeff King <[email protected]>
      Signed-off-by: default avatarJunio C Hamano <[email protected]>
  3. 05 Jul, 2017 1 commit
    • Jeff King's avatar
      reflog-walk: skip over double-null oid due to HEAD rename · 2272d3e5
      Jeff King authored
      Since 39ee4c6c (branch: record creation of renamed branch
      in HEAD's log, 2017-02-20), a rename on the currently
      checked out branch will create two entries in the HEAD
      reflog: one where the branch goes away (switching to the
      null oid), and one where it comes back (switching away from
      the null oid).
      This confuses the reflog-walk code. When walking backwards,
      it first sees the null oid in the "old" field of the second
      entry. Thanks to the "root commit" logic added by 71abeb75
      (reflog: continue walking the reflog past root commits,
      2016-06-03), we keep looking for the next entry by scanning
      the "new" field from the previous entry. But that field is
      also null! We need to go just a tiny bit further, and look
      at its "old" field. But with the current code, we decide the
      reflog has nothing else to show and just give up. To the
      user this looks like the reflog was truncated by the rename
      operation, when in fact those entries are still there.
      This patch does the absolute minimal fix, which is to look
      back that one extra level and keep traversing.
      The resulting behavior may not be the _best_ thing to do in
      the long run (for example, we show both reflog entries each
      with the same commit id), but it's a simple way to fix the
      problem without risking further regressions.
      Signed-off-by: default avatarJeff King <[email protected]>
      Signed-off-by: default avatarJunio C Hamano <[email protected]>
  4. 08 May, 2017 2 commits
    • brian m. carlson's avatar
      object: convert parse_object* to take struct object_id · c251c83d
      brian m. carlson authored
      Make parse_object, parse_object_or_die, and parse_object_buffer take a
      pointer to struct object_id.  Remove the temporary variables inserted
      earlier, since they are no longer necessary.  Transform all of the
      callers using the following semantic patch:
      expression E1;
      - parse_object(E1.hash)
      + parse_object(&E1)
      expression E1;
      - parse_object(E1->hash)
      + parse_object(E1)
      expression E1, E2;
      - parse_object_or_die(E1.hash, E2)
      + parse_object_or_die(&E1, E2)
      expression E1, E2;
      - parse_object_or_die(E1->hash, E2)
      + parse_object_or_die(E1, E2)
      expression E1, E2, E3, E4, E5;
      - parse_object_buffer(E1.hash, E2, E3, E4, E5)
      + parse_object_buffer(&E1, E2, E3, E4, E5)
      expression E1, E2, E3, E4, E5;
      - parse_object_buffer(E1->hash, E2, E3, E4, E5)
      + parse_object_buffer(E1, E2, E3, E4, E5)
      Signed-off-by: brian m. carlson's avatarbrian m. carlson <[email protected]>
      Signed-off-by: default avatarJunio C Hamano <[email protected]>
    • Johannes Schindelin's avatar
      add_reflog_for_walk: avoid memory leak · 5026b471
      Johannes Schindelin authored
      We free()d the `log` buffer when dwim_log() returned 1, but not when it
      returned a larger value (which meant that it still allocated the buffer
      but we simply ignored it).
      While in the vicinity, make sure that the `reflogs` structure as well as
      the `branch` variable are released properly, too.
      Identified by Coverity.
      Signed-off-by: Johannes Schindelin's avatarJohannes Schindelin <[email protected]>
      Signed-off-by: default avatarJunio C Hamano <[email protected]>
  5. 02 May, 2017 1 commit
  6. 27 Apr, 2017 1 commit
    • Johannes Schindelin's avatar
      timestamp_t: a new data type for timestamps · dddbad72
      Johannes Schindelin authored
      Git's source code assumes that unsigned long is at least as precise as
      time_t. Which is incorrect, and causes a lot of problems, in particular
      where unsigned long is only 32-bit (notably on Windows, even in 64-bit
      So let's just use a more appropriate data type instead. In preparation
      for this, we introduce the new `timestamp_t` data type.
      By necessity, this is a very, very large patch, as it has to replace all
      timestamps' data type in one go.
      As we will use a data type that is not necessarily identical to `time_t`,
      we need to be very careful to use `time_t` whenever we interact with the
      system functions, and `timestamp_t` everywhere else.
      Signed-off-by: Johannes Schindelin's avatarJohannes Schindelin <[email protected]>
      Signed-off-by: default avatarJunio C Hamano <[email protected]>
  7. 22 Feb, 2017 3 commits
  8. 06 Jun, 2016 1 commit
    • SZEDER Gábor's avatar
      reflog: continue walking the reflog past root commits · 71abeb75
      SZEDER Gábor authored
      If a repository contains more than one root commit, then its HEAD
      reflog may contain multiple "creation events", i.e. entries whose
      "from" value is the null sha1.  Listing such a reflog currently stops
      prematurely at the first such entry, even when the reflog still
      contains older entries.  This can scare users into thinking that their
      reflog got truncated after 'git checkout --orphan'.
      Continue walking the reflog past such creation events based on the
      preceeding reflog entry's "new" value.
      The test 'symbolic-ref writes reflog entry' in t1401-symbolic-ref
      implicitly relies on the current behavior of the reflog walker to stop
      at a root commit and thus to list only the reflog entries that are
      relevant for that test.  Adjust the test to explicitly specify the
      number of relevant reflog entries to be listed.
      Reported-by: default avatarPatrik Gustafsson <[email protected]>
      Signed-off-by: default avatarSZEDER Gábor <[email protected]>
      Signed-off-by: default avatarJunio C Hamano <[email protected]>
  9. 05 Jan, 2016 1 commit
  10. 25 Sep, 2015 1 commit
  11. 29 Jun, 2015 1 commit
    • Jeff King's avatar
      convert "enum date_mode" into a struct · a5481a6c
      Jeff King authored
      In preparation for adding date modes that may carry extra
      information beyond the mode itself, this patch converts the
      date_mode enum into a struct.
      Most of the conversion is fairly straightforward; we pass
      the struct as a pointer and dereference the type field where
      necessary. Locations that declare a date_mode can use a "{}"
      constructor.  However, the tricky case is where we use the
      enum labels as constants, like:
        show_date(t, tz, DATE_NORMAL);
      Ideally we could say:
        show_date(t, tz, &{ DATE_NORMAL });
      but of course C does not allow that. Likewise, we cannot
      cast the constant to a struct, because we need to pass an
      actual address. Our options are basically:
        1. Manually add a "struct date_mode d = { DATE_NORMAL }"
           definition to each caller, and pass "&d". This makes
           the callers uglier, because they sometimes do not even
           have their own scope (e.g., they are inside a switch
        2. Provide a pre-made global "date_normal" struct that can
           be passed by address. We'd also need "date_rfc2822",
           "date_iso8601", and so forth. But at least the ugliness
           is defined in one place.
        3. Provide a wrapper that generates the correct struct on
           the fly. The big downside is that we end up pointing to
           a single global, which makes our wrapper non-reentrant.
           But show_date is already not reentrant, so it does not
      This patch implements 3, along with a minor macro to keep
      the size of the callers sane.
      Signed-off-by: default avatarJeff King <[email protected]>
      Signed-off-by: default avatarJunio C Hamano <[email protected]>
  12. 15 Oct, 2014 1 commit
  13. 02 Sep, 2014 1 commit
  14. 27 May, 2014 1 commit
  15. 06 Mar, 2014 1 commit
  16. 03 Mar, 2014 1 commit
  17. 07 May, 2012 1 commit
  18. 04 May, 2012 2 commits
    • Jeff King's avatar
      reflog-walk: always make [email protected]{0} show indexed selectors · 794151e9
      Jeff King authored
      When we are showing reflog selectors during a walk, we infer
      from context whether the user wanted to see the index in
      each selector, or the reflog date. The current rules are:
        1. if the user asked for an explicit date format in the
           output, show the date
        2. if the user asked for [email protected]{now}, show the date
        3. if neither is true, show the index
      However,  if we see "[email protected]{0}", that should be a strong clue
      that the user wants to see the counted version. In fact, it
      should be much stronger than the date format in (1). The
      user may have been setting the date format to use in another
      part of the output (e.g., in --format="%gd (%ad)", they may
      have wanted to influence the author date).
      This patch flips the rules to:
        1. if the user asked for [email protected]{0}, always show the index
        2. if the user asked for [email protected]{now}, always show the date
        3. otherwise, we have just "ref"; show them counted by
           default, but respect the presence of "--date" as a clue
           that the user wanted them date-based
      Signed-off-by: default avatarJeff King <[email protected]>
      Signed-off-by: default avatarJunio C Hamano <[email protected]>
    • Jeff King's avatar
      reflog-walk: clean up "flag" field of commit_reflog struct · a763126b
      Jeff King authored
      When we prepare to walk a reflog, we parse the specification
      and pull some information from it, such as which reflog to
      look in (e.g., HEAD), and where to start (e.g., [email protected]{10} or
      [email protected]{yesterday}). The resulting struct has a "recno" field
      to show where in the reflog we are starting. It also has a
      "flag" field; if true, it means the recno field came from
      parsing a date like [email protected]{yesterday}.
      There are two problems with this:
        1. "flag" is an absolutely terrible name, as it conveys
           nothing about the meaning
        2. you can tell "HEAD" from "[email protected]{yesterday}", but you
           can't differentiate "HEAD" from "HEAD{0}"
      This patch converts the flag into a tri-state (and gives it
      a better name!).
      Signed-off-by: default avatarJeff King <[email protected]>
      Signed-off-by: default avatarJunio C Hamano <[email protected]>
  19. 16 Dec, 2011 1 commit
  20. 13 Dec, 2011 1 commit
  21. 06 Dec, 2011 1 commit
    • Duy Nguyen's avatar
      Copy resolve_ref() return value for longer use · d5a35c11
      Duy Nguyen authored
      resolve_ref() may return a pointer to a static buffer. Callers that
      use this value longer than a couple of statements should copy the
      value to avoid some hidden resolve_ref() call that may change the
      static buffer's value.
      The bug found by Tony Wang <[email protected]> in builtin/merge.c
      demonstrates this. The first call is in cmd_merge()
      branch = resolve_ref("HEAD", head_sha1, 0, &flag);
      Then deep in lookup_commit_or_die() a few lines after, resolve_ref()
      may be called again and destroy "branch".
      All call sites are checked and made sure that xstrdup() is called if
      the value should be saved.
      Signed-off-by: Duy Nguyen's avatarNguyễn Thái Ngọc Duy <[email protected]>
      Signed-off-by: default avatarJunio C Hamano <[email protected]>
  22. 24 Nov, 2010 1 commit
    • Jeff King's avatar
      reflogs: clear flags properly in corner case · ffa1eeae
      Jeff King authored
      The reflog-walking mechanism is based on the regular
      revision traversal. We just rewrite the parents of each
      commit in fake_reflog_parent to point to the commit in the
      next reflog entry instead of the real parents.
      However, the regular revision traversal tries not to show
      the same commit twice, and so sets the SHOWN flag on each
      commit it shows. In a reflog, however, we may want to see
      the same commit more than once if it appears in the reflog
      multiple times (which easily happens, for example, if you do
      a reset to a prior state).
      The fake_reflog_parent function takes care of this by
      clearing flags, including SHOWN. Unfortunately, it does so
      at the very end of the function, and it is possible to
      return early from the function if there is no fake parent to
      set up (e.g., because we are at the very first reflog entry
      on the branch). In such a case the flag is not cleared, and
      the entry is skipped by the revision traversal machinery as
      already shown.
      You can see this by walking the log of a ref which is set to
      its very first commit more than once (the test below shows
      such a situation). In this case the reflog walk will fail to
      show the entry for the initial creation of the ref.
      We don't want to simply move the flag-clearing to the top of
      the function; we want to make sure flags set during the
      fake-parent installation are also cleared. Instead, let's
      hoist the flag-clearing out of the fake_reflog_parent
      function entirely. It's not really about fake parents
      anyway, and the only caller is the get_revision machinery.
      Reported-by: default avatarMartin von Zweigbergk <[email protected]>
      Signed-off-by: default avatarJeff King <[email protected]>
      Acked-by: Johannes Schindelin's avatarJohannes Schindelin <[email protected]>
      Signed-off-by: default avatarJunio C Hamano <[email protected]>
  23. 27 Jun, 2010 2 commits
  24. 20 Oct, 2009 2 commits
    • Thomas Rast's avatar
      Introduce new pretty formats %g[sdD] for reflog information · 8f8f5476
      Thomas Rast authored
      Add three new --pretty=format escapes:
        %gD  long  reflog descriptor (e.g. refs/[email protected]{0})
        %gd  short reflog descriptor (e.g. [email protected]{0})
        %gs  reflog message
      This is achieved by passing down the reflog info, if any, inside the
      pretty_print_context struct.
      We use the newly refactored get_reflog_selector(), and give it some
      extra functionality to extract a shortened ref.  The shortening is
      cached inside the commit_reflogs struct; the only allocation of it
      happens in read_complete_reflog(), where it is initialised to 0.  Also
      add another helper get_reflog_message() for the message extraction.
      Note that the --format="%h %gD: %gs" tests may not work in real
      repositories, as the --pretty formatter doesn't know to leave away the
      ": " on the last commit in an incomplete (because git-gc removed the
      old part) reflog.  This equivalence is nevertheless the main goal of
      this patch.
      Thanks to Jeff King for reviews, the %gd testcase and documentation.
      Signed-off-by: default avatarThomas Rast <[email protected]>
      Signed-off-by: default avatarJunio C Hamano <[email protected]>
    • Thomas Rast's avatar
      reflog-walk: refactor the [email protected]{num} formatting · 72b103fe
      Thomas Rast authored
      We'll use the same output in an upcoming commit, so refactor its
      formatting (which was duplicated anyway) into a separate function.
      Signed-off-by: default avatarThomas Rast <[email protected]>
      Signed-off-by: default avatarJunio C Hamano <[email protected]>
  25. 01 May, 2009 1 commit
  26. 20 Mar, 2009 1 commit
    • Jeff King's avatar
      make oneline reflog dates more consistent with multiline format · cd437120
      Jeff King authored
      The multiline reflog format (e.g., as shown by "git log -g")
      will show [email protected]{<date>} rather than [email protected]{<count>} in two
        1. If the user gave [email protected]{<date>} syntax to specify the
        2. If the user gave a --date=<format> specifier
      It uses the "normal" date format in case 1, and the
      user-specified format in case 2.
      The oneline reflog format (e.g., "git reflog show" or "git
      log -g --oneline") will show the date in the same two
      circumstances. However, it _always_ shows the date as a
      relative date, and it always ignores the timezone.
      In case 2, it seems ridiculous to trigger the date but use a
      format totally different from what the user requested.
      For case 1, it is arguable that the user might want to see
      the relative date by default; however, the multiline version
      shows the normal format.
      This patch does three things:
        - refactors the "relative_date" parameter to
          show_reflog_message to be an actual date_mode enum,
          since this is how it is used (it is passed to show_date)
        - uses the passed date_mode parameter in the oneline
          format (making it consistent with the multiline format)
        - does not ignore the timezone parameter in oneline mode
      Signed-off-by: default avatarJeff King <[email protected]>
      Signed-off-by: default avatarJunio C Hamano <[email protected]>
  27. 22 Jul, 2008 1 commit
    • Johannes Schindelin's avatar
      Rename path_list to string_list · c455c87c
      Johannes Schindelin authored
      The name path_list was correct for the first usage of that data structure,
      but it really is a general-purpose string list.
      $ perl -i -pe 's/path-list/string-list/g' $(git grep -l path-list)
      $ perl -i -pe 's/path_list/string_list/g' $(git grep -l path_list)
      $ git mv path-list.h string-list.h
      $ git mv path-list.c string-list.c
      $ perl -i -pe 's/has_path/has_string/g' $(git grep -l has_path)
      $ perl -i -pe 's/path/string/g' string-list.[ch]
      $ git mv Documentation/technical/api-path-list.txt \
      $ perl -i -pe 's/strdup_paths/strdup_strings/g' $(git grep -l strdup_paths)
      ... and then fix all users of string-list to access the member "string"
      instead of "path".
      Documentation/technical/api-string-list.txt needed some rewrapping, too.
      Signed-off-by: Johannes Schindelin's avatarJohannes Schindelin <[email protected]>
      Signed-off-by: default avatarJunio C Hamano <[email protected]>
  28. 25 Jul, 2007 1 commit
  29. 09 Feb, 2007 2 commits