Commit graph

56 commits

Author SHA1 Message Date
René Scharfe
efbd4fdfc9 refs: pass NULL to resolve_refdup() if hash is not needed
This allows us to get rid of several write-only variables.

Signed-off-by: Rene Scharfe <l.s.r@web.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-10-01 17:27:14 +09:00
Jeff King
de239446b6 reflog-walk: apply --since/--until to reflog dates
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: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-07-09 10:00:48 -07:00
Jeff King
d08565bf2d reflog-walk: stop using fake parents
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
     traversal:

       -  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: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-07-09 10:00:48 -07:00
Jeff King
7f97de5ee1 rev-list: check reflog_info before showing usage
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: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-07-09 10:00:48 -07:00
Junio C Hamano
be5982a794 Merge branch 'jk/reflog-walk-maint' into jk/reflog-walk
* jk/reflog-walk-maint:
  reflog-walk: include all fields when freeing complete_reflogs
  reflog-walk: don't free reflogs added to cache
  reflog-walk: duplicate strings in complete_reflogs list
  reflog-walk: skip over double-null oid due to HEAD rename
2017-07-07 10:02:42 -07:00
Jeff King
e30d463d45 reflog-walk: include all fields when freeing complete_reflogs
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 5026b47175 (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: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-07-07 09:04:34 -07:00
Jeff King
8aae3cf755 reflog-walk: don't free reflogs added to cache
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
one.

Since 5026b47175 (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
present).

The new test in t1411 exercises this case and fails when run
with --valgrind or ASan.

Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-07-07 09:00:31 -07:00
Jeff King
75afe7ac87 reflog-walk: duplicate strings in complete_reflogs list
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 5026b47175 (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
here.

The new test reliably shows the problem when run with
--valgrind or ASAN.

Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-07-07 08:58:17 -07:00
Jeff King
2272d3e542 reflog-walk: skip over double-null oid due to HEAD rename
Since 39ee4c6c2f (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 71abeb753f
(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: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-07-05 10:34:00 -07:00
Junio C Hamano
849e671b52 Merge branch 'js/plug-leaks'
Fix memory leaks pointed out by Coverity (and people).

* js/plug-leaks: (26 commits)
  checkout: fix memory leak
  submodule_uses_worktrees(): plug memory leak
  show_worktree(): plug memory leak
  name-rev: avoid leaking memory in the `deref` case
  remote: plug memory leak in match_explicit()
  add_reflog_for_walk: avoid memory leak
  shallow: avoid memory leak
  line-log: avoid memory leak
  receive-pack: plug memory leak in update()
  fast-export: avoid leaking memory in handle_tag()
  mktree: plug memory leaks reported by Coverity
  pack-redundant: plug memory leak
  setup_discovered_git_dir(): plug memory leak
  setup_bare_git_dir(): help static analysis
  split_commit_in_progress(): simplify & fix memory leak
  checkout: fix memory leak
  cat-file: fix memory leak
  mailinfo & mailsplit: check for EOF while parsing
  status: close file descriptor after reading git-rebase-todo
  difftool: address a couple of resource/memory leaks
  ...
2017-05-29 12:34:44 +09:00
Junio C Hamano
6b526ced6f Merge branch 'bc/object-id'
Conversion from uchar[20] to struct object_id continues.

* bc/object-id: (53 commits)
  object: convert parse_object* to take struct object_id
  tree: convert parse_tree_indirect to struct object_id
  sequencer: convert do_recursive_merge to struct object_id
  diff-lib: convert do_diff_cache to struct object_id
  builtin/ls-tree: convert to struct object_id
  merge: convert checkout_fast_forward to struct object_id
  sequencer: convert fast_forward_to to struct object_id
  builtin/ls-files: convert overlay_tree_on_cache to object_id
  builtin/read-tree: convert to struct object_id
  sha1_name: convert internals of peel_onion to object_id
  upload-pack: convert remaining parse_object callers to object_id
  revision: convert remaining parse_object callers to object_id
  revision: rename add_pending_sha1 to add_pending_oid
  http-push: convert process_ls_object and descendants to object_id
  refs/files-backend: convert many internals to struct object_id
  refs: convert struct ref_update to use struct object_id
  ref-filter: convert some static functions to struct object_id
  Convert struct ref_array_item to struct object_id
  Convert the verify_pack callback to struct object_id
  Convert lookup_tag to struct object_id
  ...
2017-05-29 12:34:43 +09:00
brian m. carlson
c251c83df2 object: convert parse_object* to take struct object_id
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 <sandals@crustytoothpaste.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-05-08 15:12:58 +09:00
Johannes Schindelin
5026b47175 add_reflog_for_walk: avoid memory leak
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 <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-05-08 12:18:20 +09:00
brian m. carlson
fb4e352b40 Clean up outstanding object_id transforms.
The semantic patch for standard object_id transforms found two
outstanding places where we could make a transformation automatically.
Apply these changes.

Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-05-02 10:46:41 +09:00
Johannes Schindelin
dddbad728c timestamp_t: a new data type for timestamps
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
versions).

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 <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-04-27 13:07:39 +09:00
brian m. carlson
9461d27240 refs: convert each_reflog_ent_fn to struct object_id
Make each_reflog_ent_fn take two struct object_id pointers instead of
two pointers to unsigned char.  Convert the various callbacks to use
struct object_id as well.  Also, rename fsck_handle_reflog_sha1 to
fsck_handle_reflog_oid.

Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-02-22 10:12:15 -08:00
brian m. carlson
8ebc3fd01b reflog-walk: convert struct reflog_info to struct object_id
Convert struct reflog_info to use struct object_id by changing the
structure definition and applying the following semantic patch:

@@
struct reflog_info E1;
@@
- E1.osha1
+ E1.ooid.hash

@@
struct reflog_info *E1;
@@
- E1->osha1
+ E1->ooid.hash

@@
struct reflog_info E1;
@@
- E1.nsha1
+ E1.noid.hash

@@
struct reflog_info *E1;
@@
- E1->nsha1
+ E1->noid.hash

Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-02-22 10:12:15 -08:00
brian m. carlson
2928325fc0 Convert remaining callers of resolve_refdup to object_id
There are a few leaf functions in various files that call
resolve_refdup.  Convert these functions to use struct object_id
internally to prepare for transitioning resolve_refdup itself.

Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-02-22 10:12:15 -08:00
SZEDER Gábor
71abeb753f reflog: continue walking the reflog past root commits
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: Patrik Gustafsson <pvn@textalk.se>
Signed-off-by: SZEDER Gábor <szeder@ira.uka.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2016-06-06 15:06:44 -07:00
Junio C Hamano
ceef512e79 Merge branch 'dk/reflog-walk-with-non-commit'
"git reflog" incorrectly assumed that all objects that used to be
at the tip of a ref must be commits, which caused it to segfault.

* dk/reflog-walk-with-non-commit:
  reflog-walk: don't segfault on non-commit sha1's in the reflog
2016-01-20 11:43:32 -08:00
Dennis Kaarsemaker
aecad374ae reflog-walk: don't segfault on non-commit sha1's in the reflog
git reflog (ab)uses the log machinery to display its list of log
entries. To do so it must fake commit parent information for the log
walker.

For refs in refs/heads this is no problem, as they should only ever
point to commits. Tags and other refs however can point to anything,
thus their reflog may contain non-commit objects.

To avoid segfaulting, we check whether reflog entries are commits before
feeding them to the log walker and skip any non-commits. This means that
git reflog output will be incomplete for such refs, but that's one step
up from segfaulting. A more complete solution would be to decouple git
reflog from the log walker machinery.

Signed-off-by: Dennis Kaarsemaker <dennis@kaarsemaker.net>
Helped-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
Helped-by: Junio C Hamano <gitster@pobox.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2016-01-05 13:41:06 -08:00
Jeff King
75faa45ae0 replace trivial malloc + sprintf / strcpy calls with xstrfmt
It's a common pattern to do:

  foo = xmalloc(strlen(one) + strlen(two) + 1 + 1);
  sprintf(foo, "%s %s", one, two);

(or possibly some variant with strcpy()s or a more
complicated length computation).  We can switch these to use
xstrfmt, which is shorter, involves less error-prone manual
computation, and removes many sprintf and strcpy calls which
make it harder to audit the code for real buffer overflows.

Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2015-09-25 10:18:18 -07:00
Jeff King
a5481a6c94 convert "enum date_mode" into a struct
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
     statement).

  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
     matter.

This patch implements 3, along with a minor macro to keep
the size of the callers sane.

Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2015-06-29 11:39:07 -07:00
Ronnie Sahlberg
7695d118e5 refs.c: change resolve_ref_unsafe reading argument to be a flags field
resolve_ref_unsafe takes a boolean argument for reading (a nonexistent ref
resolves successfully for writing but not for reading).  Change this to be
a flags field instead, and pass the new constant RESOLVE_REF_READING when
we want this behaviour.

While at it, swap two of the arguments in the function to put output
arguments at the end.  As a nice side effect, this ensures that we can
catch callers that were unaware of the new API so they can be audited.

Give the wrapper functions resolve_refdup and read_ref_full the same
treatment for consistency.

Signed-off-by: Ronnie Sahlberg <sahlberg@google.com>
Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-10-15 10:47:24 -07:00
David Aguilar
24d36f1472 stylefix: asterisks stick to the variable, not the type
Signed-off-by: David Aguilar <davvid@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-09-02 11:33:32 -07:00
Brian Gesiak
8e1aa2f792 reflog-walk.c: rearrange xcalloc arguments
xcalloc() takes two arguments: the number of elements and their size.
reflog-walk.c includes several calls to xcalloc() that pass the arguments
in reverse order.

Rearrange them so they are in the correct order.

Signed-off-by: Brian Gesiak <modocache@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-05-27 14:02:45 -07:00
Junio C Hamano
006f678780 Merge branch 'sh/use-hashcpy'
* sh/use-hashcpy:
  Use hashcpy() when copying object names
2014-03-18 13:51:05 -07:00
Sun He
50546b15ed Use hashcpy() when copying object names
We invented hashcpy() to keep the abstraction of "object name"
behind it.  Use it instead of calling memcpy() with hard-coded
20-byte length when moving object names between pieces of memory.

Leave ppc/sha1.c as-is, because the function is about the SHA-1 hash
algorithm whose output is and will always be 20 bytes.

Helped-by: Michael Haggerty <mhagger@alum.mit.edu>
Helped-by: Duy Nguyen <pclouds@gmail.com>
Signed-off-by: Sun He <sunheehnus@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-03-06 14:03:12 -08:00
Dmitry S. Dolzhenko
6647cc2626 reflog-walk.c: use ALLOC_GROW()
Use ALLOC_GROW() instead of open-coding it in add_commit_info() and
read_one_reflog().

Signed-off-by: Dmitry S. Dolzhenko <dmitrys.dolzhenko@yandex.ru>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-03-03 14:53:57 -08:00
Junio C Hamano
d318a3997a Merge branch 'jk/maint-reflog-walk-count-vs-time'
Gives a better DWIM behaviour for --pretty=format:%gd, "stash list", and
"log -g", depending on how the starting point ("master" vs "master@{0}" vs
"master@{now}") and date formatting options (e.g. "--date=iso") are given
on the command line.

By Jeff King (4) and Junio C Hamano (1)
* jk/maint-reflog-walk-count-vs-time:
  reflog-walk: tell explicit --date=default from not having --date at all
  reflog-walk: always make HEAD@{0} show indexed selectors
  reflog-walk: clean up "flag" field of commit_reflog struct
  log: respect date_mode_explicit with --format:%gd
  t1411: add more selector index/date tests
2012-05-11 11:30:08 -07:00
Junio C Hamano
55ccf85a52 reflog-walk: tell explicit --date=default from not having --date at all
Introduction of opt->date_mode_explicit was a step in the right direction,
but lost that crucial bit at the very end of the callchain, and the callee
could not tell an explicitly specified "I want *date* but in default format"
from the built-in default value passed when there was no --date specified.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
2012-05-07 14:18:06 -07:00
Jeff King
794151e9b5 reflog-walk: always make HEAD@{0} show indexed selectors
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 ref@{now}, show the date

  3. if neither is true, show the index

However,  if we see "ref@{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 ref@{0}, always show the index

  2. if the user asked for ref@{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: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2012-05-04 09:39:14 -07:00
Jeff King
a763126b5c reflog-walk: clean up "flag" field of commit_reflog struct
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., HEAD@{10} or
HEAD@{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 HEAD@{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 "HEAD@{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: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2012-05-04 09:39:14 -07:00
Junio C Hamano
adb86762e5 Merge branch 'jk/pretty-reglog-ent'
* jk/pretty-reglog-ent:
  pretty: give placeholders to reflog identity
2011-12-22 11:27:28 -08:00
Jeff King
cd1957f5fc pretty: give placeholders to reflog identity
When doing a reflog walk, you can get some information about
the reflog (such as the subject line), but not the identity
information (i.e., name and email).

Let's make those available, mimicing the options for author
and committer identity.

Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2011-12-16 13:00:15 -08:00
Nguyễn Thái Ngọc Duy
96ec7b1e70 Convert resolve_ref+xstrdup to new resolve_refdup function
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2011-12-13 09:26:52 -08:00
Nguyễn Thái Ngọc Duy
d5a35c114a Copy resolve_ref() return value for longer use
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 <wwwjfy@gmail.com> 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".

lookup_commit_or_die
 lookup_commit_reference
  lookup_commit_reference_gently
   parse_object
    lookup_replace_object
     do_lookup_replace_object
      prepare_replace_object
       for_each_replace_ref
        do_for_each_ref
         get_loose_refs
          get_ref_dir
           get_ref_dir
            resolve_ref

All call sites are checked and made sure that xstrdup() is called if
the value should be saved.

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2011-12-05 16:21:06 -08:00
Junio C Hamano
9f5074e034 Merge branch 'jk/maint-reflog-bottom'
* jk/maint-reflog-bottom:
  reflogs: clear flags properly in corner case
2010-12-12 21:49:51 -08:00
Jeff King
ffa1eeaeea reflogs: clear flags properly in corner case
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: Martin von Zweigbergk <martin.von.zweigbergk@gmail.com>
Signed-off-by: Jeff King <peff@peff.net>
Acked-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2010-11-23 16:24:24 -08:00
Julian Phillips
e8c8b7139c string_list: Fix argument order for string_list_lookup
Update the definition and callers of string_list_lookup to use the
string_list as the first argument.  This helps make the string_list
API easier to use by being more consistent.

Signed-off-by: Julian Phillips <julian@quantumfyre.co.uk>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2010-06-27 10:06:51 -07:00
Julian Phillips
78a395d371 string_list: Fix argument order for string_list_insert
Update the definition and callers of string_list_insert to use the
string_list as the first argument.  This helps make the string_list
API easier to use by being more consistent.

Signed-off-by: Julian Phillips <julian@quantumfyre.co.uk>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2010-06-27 10:06:51 -07:00
Thomas Rast
8f8f5476cd Introduce new pretty formats %g[sdD] for reflog information
Add three new --pretty=format escapes:

  %gD  long  reflog descriptor (e.g. refs/stash@{0})
  %gd  short reflog descriptor (e.g. stash@{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: Thomas Rast <trast@student.ethz.ch>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2009-10-19 22:28:26 -07:00
Thomas Rast
72b103fec7 reflog-walk: refactor the branch@{num} formatting
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: Thomas Rast <trast@student.ethz.ch>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2009-10-19 22:28:25 -07:00
Felipe Contreras
4b25d091ba Fix a bunch of pointer declarations (codestyle)
Essentially; s/type* /type */ as per the coding guidelines.

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2009-05-01 15:17:31 -07:00
Jeff King
cd4371208a make oneline reflog dates more consistent with multiline format
The multiline reflog format (e.g., as shown by "git log -g")
will show HEAD@{<date>} rather than HEAD@{<count>} in two
situations:

  1. If the user gave branch@{<date>} syntax to specify the
     reflog

  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: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2009-03-20 00:57:27 -07:00
Johannes Schindelin
c455c87c5c Rename path_list to string_list
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 \
	Documentation/technical/api-string-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 <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2008-07-21 19:11:50 -07:00
Johannes Schindelin
7b69b873fa git log -g: Complain, but do not fail, when no reflogs are there
When asking "git log -g --all", clearly you want to see only those refs
that do have reflogs, but you do not want it to fail, either.

So instead of die()ing, complain about it, but move on to the other refs.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2007-07-24 17:28:10 -07:00
Johannes Schindelin
eb3a48221f log --reflog: use dwim_log
Since "git log origin/master" uses dwim_log() to match
"refs/remotes/origin/master", it makes sense to do that for
"git log --reflog", too.

Signed-off-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-02-08 17:48:22 -08:00
Johannes Schindelin
4e244cbc5c log --reflog: honour --relative-date
If you say "git log -g --relative-date", it is very likely that
you want to see the reflog names in terms of a relative date.

Signed-off-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-02-08 16:20:52 -08:00
Johannes Schindelin
d271fd5311 Teach the '@{...}' notation to git-log -g
Signed-off-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-02-01 21:50:16 -08:00