Re: [PATCH v2 000/142] Use the $( ... ) construct for command substitution instead of using the back-quotes

2014-03-26 Thread Matthieu Moy
Junio C Hamano  writes:

>  - Nobody has time or energy to go through 140+ patches in one go,
>with enough concentration necessary to do so without making
>mistakes (this applies to yourself, too---producing mechanical
>replacement is a no-cost thing, finding mistakes in mechanical
>replacement takes real effort).

It's a bit less bad than it seems:

 142 files changed, 609 insertions(+), 609 deletions(-)

The first pass I did was a very quick one, but I already went through
the patches I received (apparently not the whole series) and it wasn't
that long.

-- 
Matthieu Moy
http://www-verimag.imag.fr/~moy/
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 1/6] t/perf-lib: factor boilerplate out of test_perf

2014-03-26 Thread Jeff King
About half of test_perf() is boilerplate, and half is
actually related to running the perf test. Let's split it
into two functions, so that we can reuse the boilerplate in
future commits.

Signed-off-by: Jeff King 
---
 t/perf/perf-lib.sh | 61 +++---
 1 file changed, 35 insertions(+), 26 deletions(-)

diff --git a/t/perf/perf-lib.sh b/t/perf/perf-lib.sh
index a8c9574..20f306a 100644
--- a/t/perf/perf-lib.sh
+++ b/t/perf/perf-lib.sh
@@ -150,8 +150,8 @@ exit $ret' >&3 2>&4
return "$eval_ret"
 }
 
-
-test_perf () {
+test_wrapper_ () {
+   test_wrapper_func_=$1; shift
test_start_
test "$#" = 3 && { test_prereq=$1; shift; } || test_prereq=
test "$#" = 2 ||
@@ -162,35 +162,44 @@ test_perf () {
base=$(basename "$0" .sh)
echo "$test_count" >>"$perf_results_dir"/$base.subtests
echo "$1" >"$perf_results_dir"/$base.$test_count.descr
-   if test -z "$verbose"; then
-   printf "%s" "perf $test_count - $1:"
-   else
-   echo "perf $test_count - $1:"
-   fi
-   for i in $(test_seq 1 $GIT_PERF_REPEAT_COUNT); do
-   say >&3 "running: $2"
-   if test_run_perf_ "$2"
-   then
-   if test -z "$verbose"; then
-   printf " %s" "$i"
-   else
-   echo "* timing run 
$i/$GIT_PERF_REPEAT_COUNT:"
-   fi
+   base="$perf_results_dir"/"$perf_results_prefix$(basename "$0" 
.sh)"."$test_count"
+   "$test_wrapper_func_" "$@"
+   fi
+
+   test_finish_
+}
+
+test_perf_ () {
+   if test -z "$verbose"; then
+   printf "%s" "perf $test_count - $1:"
+   else
+   echo "perf $test_count - $1:"
+   fi
+   for i in $(test_seq 1 $GIT_PERF_REPEAT_COUNT); do
+   say >&3 "running: $2"
+   if test_run_perf_ "$2"
+   then
+   if test -z "$verbose"; then
+   printf " %s" "$i"
else
-   test -z "$verbose" && echo
-   test_failure_ "$@"
-   break
+   echo "* timing run $i/$GIT_PERF_REPEAT_COUNT:"
fi
-   done
-   if test -z "$verbose"; then
-   echo " ok"
else
-   test_ok_ "$1"
+   test -z "$verbose" && echo
+   test_failure_ "$@"
+   break
fi
-   base="$perf_results_dir"/"$perf_results_prefix$(basename "$0" 
.sh)"."$test_count"
-   "$TEST_DIRECTORY"/perf/min_time.perl test_time.* >"$base".times
+   done
+   if test -z "$verbose"; then
+   echo " ok"
+   else
+   test_ok_ "$1"
fi
-   test_finish_
+   "$TEST_DIRECTORY"/perf/min_time.perl test_time.* >"$base".times
+}
+
+test_perf () {
+   test_wrapper_ test_perf_ "$@"
 }
 
 # We extend test_done to print timings at the end (./run disables this
-- 
1.9.1.601.g7ec968e

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 4/6] t/perf: add perf tests for fetches from a bitmapped server

2014-03-26 Thread Jeff King
A server with bitmapped packs can serve a clone very
quickly. However, fetches are not necessarily made any
faster, because we spend a lot less time in object traversal
(which is what bitmaps help with) and more time finding
deltas (because we may have to throw out on-disk deltas if
the client does not have the other side).

As a first step to making this faster, this patch introduces
a new perf script to measure fetches into a repo of various
ages from a fully-bitmapped server.

We separately measure the work done by the server (in
pack-objects) and that done by the client (in index-pack).
Furthermore, we measure the size of the resulting pack.

Breaking it down like this (instead of just doing a regular
"git fetch") lets us see how much each side benefits from
any changes. And since we know the pack size, if we estimate
the network speed, then we can calculate a complete
wall-clock time for the operation.

Signed-off-by: Jeff King 
---
 t/perf/p5311-pack-bitmaps-fetch.sh | 45 ++
 1 file changed, 45 insertions(+)
 create mode 100755 t/perf/p5311-pack-bitmaps-fetch.sh

diff --git a/t/perf/p5311-pack-bitmaps-fetch.sh 
b/t/perf/p5311-pack-bitmaps-fetch.sh
new file mode 100755
index 000..b045759
--- /dev/null
+++ b/t/perf/p5311-pack-bitmaps-fetch.sh
@@ -0,0 +1,45 @@
+#!/bin/sh
+
+test_description='performance of fetches from bitmapped packs'
+. ./perf-lib.sh
+
+test_perf_default_repo
+
+test_expect_success 'create bitmapped server repo' '
+   git config pack.writebitmaps true &&
+   git config pack.writebitmaphashcache true &&
+   git repack -ad
+'
+
+# simulate a fetch from a repository that last fetched N days ago, for
+# various values of N. We do so by following the first-parent chain,
+# and assume the first entry in the chain that is N days older than the current
+# HEAD is where the HEAD would have been then.
+for days in 1 2 4 8 16 32 64 128; do
+   title=$(printf '%10s' "($days days)")
+   test_expect_success "setup revs from $days days ago" '
+   now=$(git log -1 --format=%ct HEAD) &&
+   then=$(($now - ($days * 86400))) &&
+   tip=$(git rev-list -1 --first-parent --until=$then HEAD) &&
+   {
+   echo HEAD &&
+   echo ^$tip
+   } >revs
+   '
+
+   test_perf "server $title" '
+   git pack-objects --stdout --revs \
+--thin --delta-base-offset \
+tmp.pack
+   '
+
+   test_size "size   $title" '
+   wc -c http://vger.kernel.org/majordomo-info.html


[PATCH/RFC 0/6] reuse deltas found by bitmaps

2014-03-26 Thread Jeff King
[tl;dr the patch is the same as before, but there is a script to measure
   its effects; please try it out on your repos]

This is a continuation of the discussion here:

  http://thread.gmane.org/gmane.comp.version-control.git/239647

I'll summarize the story so far.

Basically, the problem is that while pack bitmaps make the "Counting
objects" phase of a fetch fast (which in turn makes clones very fast),
they do not help as much for an incremental fetch. One, because we have
a lot fewer objects to count, so there is less for us to speed up there.
And two, we spend a lot more effort on delta compression for a fetch,
because we are often throwing out on-disk deltas that we are not sure
that the other side has.

One common case is that the server side is mostly packed and has
bitmaps, and the fetching client has some subset of its objects, but
wants to bring itself up to the tip. Any delta that the server has on
disk is generally eligible for reuse, because the base is either:

  1. An object that the client already has.

  2. An object that we are going to send as part of the new pack.

However, we quite often do not notice case (1), because we only consider
a subset of the client's objects as "preferred bases" for thin-packing.
The reason for this is that traditionally it was expensive to enumerate
all of the objects we know the client has. But with bitmaps, this is
very cheap. So the basic idea is to better notice which objects the
client has and change our delta reuse and preferred-base rules.

There are three basic strategies I can think of for doing this:

  1. Add every object the client has to the packing list as a preferred
 base.

  2. When considering whether a delta can be reused, check the bitmaps
 to see if the client has the base. If so, allow reuse.

  3. Do (2), but also add the object as a preferred base.

I think that option (1) is probably a bad idea; we'll spend a lot of
time generating a large packing list, and the huge number of objects
will probably clog the delta window.

Option (3) might or might not be a good idea. It would hopefully give us
some relevant subset of the objects to use as preferred bases, in case
other objects also need deltas.

The implementation I'm including here is the one I've shown before,
which does (2). Part of the reason that I'm reposting it before looking
further into these options is that I've written a t/perf script that can
help with the analysis.

I've run it against git.git and linux.git. I'd be curious to see the
results on other repositories that might have different delta patterns.

The script simulates a fetch from a fully-packed server by a client who
has not fetched in N days, for several values of N. It measures the time
taken on the server (to run pack-objects), the time taken on the client
(to run index-pack), and the size of the resulting pack. Here are the
results for running it on linux.git (note that the script output has the
tests interleaved, but I've rearranged it here for clarity):

Test origin HEAD   
---
5311.4: size (1 days)   1.0M  59.5K -94.1% 
5311.8: size (2 days)   1.0M  59.5K -94.1% 
5311.12: size (4 days)  1.1M  67.9K -93.5% 
5311.16: size (8 days)  1.5M 130.1K -91.4% 
5311.20: size(16 days)  3.7M 359.8K -90.3% 
5311.24: size(32 days)  8.6M   1.4M -84.3% 
5311.28: size(64 days) 68.3M  23.0M -66.3% 
5311.32: size   (128 days) 83.1M  35.1M -57.7% 

You can see that it produces much smaller packs, because we're getting
better delta reuse (and bitmaps don't generally produce preferred bases
at all, so we were probably failing to make thin packs at all). The
percentage benefit lessens as we go further back, of course, because the
thin objects will be at the "edge" of the pack (and the bigger the pack,
the less of it is edge).

So far so good...here are the server timings:

Test origin HEAD   
---
5311.3: server   (1 days)0.29(0.33+0.03)0.14(0.11+0.02) -51.7% 
5311.7: server   (2 days)0.29(0.33+0.04)0.14(0.11+0.02) -51.7% 
5311.11: server   (4 days)   0.29(0.32+0.04)0.14(0.11+0.02) -51.7% 
5311.15: server   (8 days)   0.36(0.45+0.04)0.14(0.11+0.02) -61.1% 
5311.19: server  (16 days)   0.74(1.17+0.05)0.26(0.23+0.02) -64.9% 
5311.23: server  (32 days)   1.38(2.53+0.06)0.29(0.25+0.03) -79.0% 
5311.27: server  (64 days)   7.12(15.70+0.18)   0.43(0.38+0.07) -94.0% 
5311.31: server (128 days)   7.60(16.72+0.19)   0.52(0.48+0.07) -93.2% 

Again, looking good. We'r

[PATCH 3/6] t/perf: add infrastructure for measuring sizes

2014-03-26 Thread Jeff King
The main objective of scripts in the perf framework is to
run "test_perf", which measures the time it takes to run
some operation. However, it can also be interesting to see
the change in the output size of certain operations.

This patch introduces test_size, which records a single
numeric output from the test and shows it in the aggregated
output (with pretty printing and relative size comparison).

Signed-off-by: Jeff King 
---
 t/perf/README | 20 
 t/perf/aggregate.perl | 48 +++-
 t/perf/perf-lib.sh| 13 +
 3 files changed, 76 insertions(+), 5 deletions(-)

diff --git a/t/perf/README b/t/perf/README
index 8848c14..09c400f 100644
--- a/t/perf/README
+++ b/t/perf/README
@@ -144,3 +144,23 @@ that
   While we have tried to make sure that it can cope with embedded
   whitespace and other special characters, it will not work with
   multi-line data.
+
+Rather than tracking the performance by run-time as `test_perf` does, you
+may also track output size by using `test_size`. The stdout of the
+function should be a single numeric value, which will be captured and
+shown in the aggregated output. For example:
+
+   test_perf 'time foo' '
+   ./foo >foo.out
+   '
+
+   test_size 'output size'
+   wc -c ;
return undef if not defined $line;
close $fh or die "cannot close $name: $!";
-   $line =~ /^(?:(\d+):)?(\d+):(\d+(?:\.\d+)?) (\d+(?:\.\d+)?) 
(\d+(?:\.\d+)?)$/
-   or die "bad input line: $line";
-   my $rt = ((defined $1 ? $1 : 0.0)*60+$2)*60+$3;
-   return ($rt, $4, $5);
+   # times
+   if ($line =~ /^(?:(\d+):)?(\d+):(\d+(?:\.\d+)?) (\d+(?:\.\d+)?) 
(\d+(?:\.\d+)?)$/) {
+   my $rt = ((defined $1 ? $1 : 0.0)*60+$2)*60+$3;
+   return ($rt, $4, $5);
+   # size
+   } elsif ($line =~ /^\d+$/) {
+   return $&;
+   } else {
+   die "bad input line: $line";
+   }
 }
 
 sub relative_change {
@@ -29,14 +35,39 @@ sub relative_change {
 
 sub format_times {
my ($r, $u, $s, $firstr) = @_;
+   # no value means we did not finish the test
if (!defined $r) {
return "";
}
+   # a single value means we have a size, not times
+   if (!defined $u) {
+   return format_size($r, $firstr);
+   }
+   # otherwise, we have real/user/system times
my $out = sprintf "%.2f(%.2f+%.2f)", $r, $u, $s;
$out .= ' ' . relative_change($r, $firstr) if defined $firstr;
return $out;
 }
 
+sub human_size {
+   my $n = shift;
+   my @units = ('', qw(K M G));
+   while ($n > 900 && @units > 1) {
+   $n /= 1000;
+   shift @units;
+   }
+   return $n unless length $units[0];
+   return sprintf '%.1f%s', $n, $units[0];
+}
+
+sub format_size {
+   my ($size, $first) = @_;
+   # match the width of a time: 0.00(0.00+0.00)
+   my $out = sprintf '%15s', human_size($size);
+   $out .= ' ' . relative_change($size, $first) if defined $first;
+   return $out;
+}
+
 my (@dirs, %dirnames, %dirabbrevs, %prefixes, @tests);
 while (scalar @ARGV) {
my $arg = $ARGV[0];
@@ -139,7 +170,14 @@ sub have_slash {
my $firstr;
for my $i (0..$#dirs) {
my $d = $dirs[$i];
-   $times{$prefixes{$d}.$t} = 
[get_times("test-results/$prefixes{$d}$t.times")];
+   my $base = "test-results/$prefixes{$d}$t";
+   $times{$prefixes{$d}.$t} = [];
+   foreach my $type (qw(times size)) {
+   if (-e "$base.$type") {
+   $times{$prefixes{$d}.$t} = 
[get_times("$base.$type")];
+   last;
+   }
+   }
my ($r,$u,$s) = @{$times{$prefixes{$d}.$t}};
my $w = length format_times($r,$u,$s,$firstr);
$colwidth[$i] = $w if $w > $colwidth[$i];
diff --git a/t/perf/perf-lib.sh b/t/perf/perf-lib.sh
index 20f306a..fb8e017 100644
--- a/t/perf/perf-lib.sh
+++ b/t/perf/perf-lib.sh
@@ -202,6 +202,19 @@ test_perf () {
test_wrapper_ test_perf_ "$@"
 }
 
+test_size_ () {
+   say >&3 "running: $2"
+   if test_eval_ "$2" 3>"$base".size; then
+   test_ok_ "$1"
+   else
+   test_failure_ "$@"
+   fi
+}
+
+test_size () {
+   test_wrapper_ test_size_ "$@"
+}
+
 # We extend test_done to print timings at the end (./run disables this
 # and does it after running everything)
 test_at_end_hook_ () {
-- 
1.9.1.601.g7ec968e

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 2/6] t/perf/aggregate: factor our percent calculations

2014-03-26 Thread Jeff King
This will let us reuse the code when we add new values to
aggregate besides times.

Signed-off-by: Jeff King 
---
 t/perf/aggregate.perl | 21 -
 1 file changed, 12 insertions(+), 9 deletions(-)

diff --git a/t/perf/aggregate.perl b/t/perf/aggregate.perl
index 15f7fc1..690cd8c 100755
--- a/t/perf/aggregate.perl
+++ b/t/perf/aggregate.perl
@@ -16,21 +16,24 @@ sub get_times {
return ($rt, $4, $5);
 }
 
+sub relative_change {
+   my ($r, $firstr) = @_;
+   if ($firstr > 0) {
+   return sprintf "%+.1f%%", 100.0*($r-$firstr)/$firstr;
+   } elsif ($r == 0) {
+   return "=";
+   } else {
+   return "+inf";
+   }
+}
+
 sub format_times {
my ($r, $u, $s, $firstr) = @_;
if (!defined $r) {
return "";
}
my $out = sprintf "%.2f(%.2f+%.2f)", $r, $u, $s;
-   if (defined $firstr) {
-   if ($firstr > 0) {
-   $out .= sprintf " %+.1f%%", 100.0*($r-$firstr)/$firstr;
-   } elsif ($r == 0) {
-   $out .= " =";
-   } else {
-   $out .= " +inf";
-   }
-   }
+   $out .= ' ' . relative_change($r, $firstr) if defined $firstr;
return $out;
 }
 
-- 
1.9.1.601.g7ec968e

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 5/6] pack-bitmap: save "have" bitmap from walk

2014-03-26 Thread Jeff King
When we do a bitmap walk, we save the result, which
represents (WANTs & ~HAVEs); i.e., every object we care
about visiting in our walk. However, we throw away the
haves bitmap, which can sometimes be useful, too. Save it
and provide an access function so code which has performed a
walk can query it.

Signed-off-by: Jeff King 
---
 pack-bitmap.c | 21 -
 pack-bitmap.h |  2 ++
 2 files changed, 22 insertions(+), 1 deletion(-)

diff --git a/pack-bitmap.c b/pack-bitmap.c
index a31e529..f7d417b 100644
--- a/pack-bitmap.c
+++ b/pack-bitmap.c
@@ -86,6 +86,9 @@ static struct bitmap_index {
/* Bitmap result of the last performed walk */
struct bitmap *result;
 
+   /* "have" bitmap from the last performed walk */
+   struct bitmap *haves;
+
/* Version of the bitmap index */
unsigned int version;
 
@@ -769,8 +772,8 @@ int prepare_bitmap_walk(struct rev_info *revs)
bitmap_and_not(wants_bitmap, haves_bitmap);
 
bitmap_git.result = wants_bitmap;
+   bitmap_git.haves = haves_bitmap;
 
-   bitmap_free(haves_bitmap);
return 0;
 }
 
@@ -1097,3 +1100,19 @@ int rebuild_existing_bitmaps(struct packing_data 
*mapping,
bitmap_free(rebuild);
return 0;
 }
+
+int bitmap_have(const unsigned char *sha1)
+{
+   int pos;
+
+   if (!bitmap_git.loaded)
+   return 0; /* no bitmap loaded */
+   if (!bitmap_git.haves)
+   return 0; /* walk had no "haves" */
+
+   pos = bitmap_position_packfile(sha1);
+   if (pos < 0)
+   return 0;
+
+   return bitmap_get(bitmap_git.haves, pos);
+}
diff --git a/pack-bitmap.h b/pack-bitmap.h
index 8b7f4e9..a63ee6b 100644
--- a/pack-bitmap.h
+++ b/pack-bitmap.h
@@ -49,6 +49,8 @@ int prepare_bitmap_walk(struct rev_info *revs);
 int reuse_partial_packfile_from_bitmap(struct packed_git **packfile, uint32_t 
*entries, off_t *up_to);
 int rebuild_existing_bitmaps(struct packing_data *mapping, khash_sha1 
*reused_bitmaps, int show_progress);
 
+int bitmap_have(const unsigned char *sha1);
+
 void bitmap_writer_show_progress(int show);
 void bitmap_writer_set_checksum(unsigned char *sha1);
 void bitmap_writer_build_type_index(struct pack_idx_entry **index, uint32_t 
index_nr);
-- 
1.9.1.601.g7ec968e

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 6/6] pack-objects: reuse deltas for thin "have" objects

2014-03-26 Thread Jeff King
When we calculate the "wants" and "haves" for a pack, we
only add the objects in the boundary commits as preferred
bases. However, we know that every object reachable from the
"haves" could be a preferred base.

We probably don't want to add these to our preferred base
list, because they would clog the delta-search window.
However, there is no reason we cannot reuse an on-disk delta
against such a deep "have" base, avoiding the delta search
for that object altogether.

Signed-off-by: Jeff King 
---
 builtin/pack-objects.c | 16 +++-
 1 file changed, 15 insertions(+), 1 deletion(-)

diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c
index 7950c43..92bd682 100644
--- a/builtin/pack-objects.c
+++ b/builtin/pack-objects.c
@@ -53,6 +53,7 @@ static unsigned long pack_size_limit;
 static int depth = 50;
 static int delta_search_threads;
 static int pack_to_stdout;
+static int thin = 0;
 static int num_preferred_base;
 static struct progress *progress_state;
 static int pack_compression_level = Z_DEFAULT_COMPRESSION;
@@ -1419,6 +1420,20 @@ static void check_object(struct object_entry *entry)
base_entry->delta_child = entry;
unuse_pack(&w_curs);
return;
+   } else if(thin && base_ref && bitmap_have(base_ref)) {
+   entry->type = entry->in_pack_type;
+   entry->delta_size = entry->size;
+   /*
+* XXX we'll leak this, but it's probably OK
+* since we'll exit immediately after the packing
+* is done
+*/
+   entry->delta = xcalloc(1, sizeof(*entry->delta));
+   hashcpy(entry->delta->idx.sha1, base_ref);
+   entry->delta->preferred_base = 1;
+   entry->delta->filled = 1;
+   unuse_pack(&w_curs);
+   return;
}
 
if (entry->type) {
@@ -2559,7 +2574,6 @@ static int option_parse_ulong(const struct option *opt,
 int cmd_pack_objects(int argc, const char **argv, const char *prefix)
 {
int use_internal_rev_list = 0;
-   int thin = 0;
int all_progress_implied = 0;
const char *rp_av[6];
int rp_ac = 0;
-- 
1.9.1.601.g7ec968e
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v2 000/142] Use the $( ... ) construct for command substitution instead of using the back-quotes

2014-03-26 Thread Eric Sunshine
On Wed, Mar 26, 2014 at 3:02 AM, Matthieu Moy
 wrote:
> Junio C Hamano  writes:
>
>>  - Nobody has time or energy to go through 140+ patches in one go,
>>with enough concentration necessary to do so without making
>>mistakes (this applies to yourself, too---producing mechanical
>>replacement is a no-cost thing, finding mistakes in mechanical
>>replacement takes real effort).
>
> It's a bit less bad than it seems:
>
>  142 files changed, 609 insertions(+), 609 deletions(-)
>
> The first pass I did was a very quick one, but I already went through
> the patches I received (apparently not the whole series) and it wasn't
> that long.

I also gave v2 a read-through. Nothing jumped out as a red-flag.
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [RFC/PATCH 1/4] test-lib: add test_dir_is_empty()

2014-03-26 Thread Jens Lehmann
Am 25.03.2014 21:49, schrieb Junio C Hamano:
> Jens Lehmann  writes:
> 
>> For the upcoming submodule test framework we often need to assert that an
>> empty directory exists in the work tree. Add the test_dir_is_empty()
>> function which asserts that the given argument is an empty directory.
>>
>> Signed-off-by: Jens Lehmann 
>> ---
>>
>> I believe this one is pretty straightforward (unless I missed that this
>> functionality already exists someplace I forgot to look ;-).
> 
> I am not very thrilled to see that it depends on "." and ".." to
> always exist, which may be true for all POSIX filesystems, but
> still...

Agreed. I didn't find any one-liners to do that ("ls -A" isn't
POSIX), so I decided to wrap that in a function. Testing that
"rmdir" on the directory succeeds (because the directory is
empty) would kinda work, but then we'd have to re-create the
directory afterwards, which really doesn't sound like a good
strategy either as the test would manipulate the to-be-tested
object. I'm not terribly happy with depending on "." and ".."
either, but couldn't come up with something better. At least
the test should fail for any filesystem not having the dot
files ...

> Do expected callsites of this helper care if "$1" is a symbolic link
> that points at an empty directory?

Yep, a symbolic link pointing to an empty directory should make
the test fail.

> What do expected callsites really want to ensure?  In other words,
> why do they care if the directory is empty?  Is it to make sure,
> after some operation, they can "rmdir" the directory?

To assert that a submodule is created but *not* populated. This
is intended to catch any possible fallout from the recursive
checkout later, in case that would kick in when it shouldn't.

>>  t/test-lib-functions.sh | 11 +++
>>  1 file changed, 11 insertions(+)
>>
>> diff --git a/t/test-lib-functions.sh b/t/test-lib-functions.sh
>> index 158e10a..93d10cd 100644
>> --- a/t/test-lib-functions.sh
>> +++ b/t/test-lib-functions.sh
>> @@ -489,6 +489,17 @@ test_path_is_dir () {
>>  fi
>>  }
>>
>> +# Check if the directory exists and is empty as expected, barf otherwise.
>> +test_dir_is_empty () {
>> +test_path_is_dir "$1" &&
>> +if test $(ls -a1 "$1" | wc -l) != 2
>> +then
>> +echo "Directory '$1' is not empty, it contains:"
>> +ls -la "$1"
>> +return 1
>> +fi
>> +}
>> +
>>  test_path_is_missing () {
>>  if [ -e "$1" ]
>>  then
> --
> To unsubscribe from this list: send the line "unsubscribe git" in
> the body of a message to majord...@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] Enable index-pack threading in msysgit.

2014-03-26 Thread Johannes Sixt
Am 3/19/2014 1:46, schrieb sza...@chromium.org:
> This adds a Windows implementation of pread.  Note that it is NOT
> safe to intersperse calls to read() and pread() on a file
> descriptor.  According to the ReadFile spec, using the 'overlapped'
> argument should not affect the implicit position pointer of the
> descriptor.  Experiments have shown that this is, in fact, a lie.
> 
> To accomodate that fact, this change also incorporates:
> 
> http://article.gmane.org/gmane.comp.version-control.git/196042
> 
>  which gives each index-pack thread its own file descriptor.
> ---
>  builtin/index-pack.c | 21 -
>  compat/mingw.c   | 31 ++-
>  compat/mingw.h   |  3 +++
>  config.mak.uname |  1 -
>  4 files changed, 49 insertions(+), 7 deletions(-)

t5302 does not pass with this patch (sz/mingw-index-pack-threaded).
It fails like this:

+ eval 'git index-pack --index-version=1 --stdin < "test-1-${pack1}.pack" &&
 git prune-packed &&
 git count-objects | ( read nr rest && test "$nr" -eq 1 ) &&
 cmp "test-1-${pack1}.pack" ".git/objects/pack/pack-${pack1}.pack" &&
 cmp "test-1-${pack1}.idx"  ".git/objects/pack/pack-${pack1}.idx"'
++ git index-pack --index-version=1 --stdin
pack1c54d893dd9bf6645ecee2886ea72f2c2030bea1
++ git prune-packed
error: packfile 
.git/objects/pack/pack-1c54d893dd9bf6645ecee2886ea72f2c2030bea1.pack does not 
match index
warning: packfile 
.git/objects/pack/pack-1c54d893dd9bf6645ecee2886ea72f2c2030bea1.pack cannot be 
accessed
[... these 2 messages repeat ~250 times ...]
++ git count-objects
++ read nr rest
++ test 303 -eq 1

I haven't tested Duy's latest patch (index-pack: work around
thread-unsafe pread() yesterday), yet.

-- Hannes

> 
> diff --git a/builtin/index-pack.c b/builtin/index-pack.c
> index 2f37a38..c02dd4c 100644
> --- a/builtin/index-pack.c
> +++ b/builtin/index-pack.c
> @@ -51,6 +51,7 @@ struct thread_local {
>  #endif
>   struct base_data *base_cache;
>   size_t base_cache_used;
> + int pack_fd;
>  };
>  
>  /*
> @@ -91,7 +92,8 @@ static off_t consumed_bytes;
>  static unsigned deepest_delta;
>  static git_SHA_CTX input_ctx;
>  static uint32_t input_crc32;
> -static int input_fd, output_fd, pack_fd;
> +static const char *curr_pack;
> +static int input_fd, output_fd;
>  
>  #ifndef NO_PTHREADS
>  
> @@ -134,6 +136,7 @@ static inline void unlock_mutex(pthread_mutex_t *mutex)
>   */
>  static void init_thread(void)
>  {
> + int i;
>   init_recursive_mutex(&read_mutex);
>   pthread_mutex_init(&counter_mutex, NULL);
>   pthread_mutex_init(&work_mutex, NULL);
> @@ -141,11 +144,17 @@ static void init_thread(void)
>   pthread_mutex_init(&deepest_delta_mutex, NULL);
>   pthread_key_create(&key, NULL);
>   thread_data = xcalloc(nr_threads, sizeof(*thread_data));
> + for (i = 0; i < nr_threads; i++) {
> + thread_data[i].pack_fd = open(curr_pack, O_RDONLY);
> + if (thread_data[i].pack_fd == -1)
> + die_errno("unable to open %s", curr_pack);
> + }
>   threads_active = 1;
>  }
>  
>  static void cleanup_thread(void)
>  {
> + int i;
>   if (!threads_active)
>   return;
>   threads_active = 0;
> @@ -155,6 +164,8 @@ static void cleanup_thread(void)
>   if (show_stat)
>   pthread_mutex_destroy(&deepest_delta_mutex);
>   pthread_key_delete(key);
> + for (i = 0; i < nr_threads; i++)
> + close(thread_data[i].pack_fd);
>   free(thread_data);
>  }
>  
> @@ -288,13 +299,13 @@ static const char *open_pack_file(const char *pack_name)
>   output_fd = open(pack_name, O_CREAT|O_EXCL|O_RDWR, 
> 0600);
>   if (output_fd < 0)
>   die_errno(_("unable to create '%s'"), pack_name);
> - pack_fd = output_fd;
> + nothread_data.pack_fd = output_fd;
>   } else {
>   input_fd = open(pack_name, O_RDONLY);
>   if (input_fd < 0)
>   die_errno(_("cannot open packfile '%s'"), pack_name);
>   output_fd = -1;
> - pack_fd = input_fd;
> + nothread_data.pack_fd = input_fd;
>   }
>   git_SHA1_Init(&input_ctx);
>   return pack_name;
> @@ -542,7 +553,7 @@ static void *unpack_data(struct object_entry *obj,
>  
>   do {
>   ssize_t n = (len < 64*1024) ? len : 64*1024;
> - n = pread(pack_fd, inbuf, n, from);
> + n = pread(get_thread_data()->pack_fd, inbuf, n, from);
>   if (n < 0)
>   die_errno(_("cannot pread pack file"));
>   if (!n)
> @@ -1490,7 +1501,7 @@ static void show_pack_info(int stat_only)
>  int cmd_index_pack(int argc, const char **argv, const char *prefix)
>  {
>   int i, fix_thin_pack = 0, verify = 0, stat_only = 0;
> - const char *curr_pack, *curr_index;
> + const char *curr_index;
>   const char *index_n

Re: What's cooking in git.git (Mar 2014, #06; Tue, 25)

2014-03-26 Thread Christian Couder
HI,

On Tue, Mar 25, 2014 at 9:18 PM, Junio C Hamano  wrote:
>
> * cc/interpret-trailers (2014-03-07) 11 commits
>  - Documentation: add documentation for 'git interpret-trailers'
>  - trailer: add tests for commands in config file
>  - trailer: execute command from 'trailer..command'
>  - trailer: add tests for "git interpret-trailers"
>  - trailer: add interpret-trailers command
>  - trailer: put all the processing together and print
>  - trailer: parse trailers from stdin
>  - trailer: process command line trailer arguments
>  - trailer: read and process config information
>  - trailer: process trailers from stdin and arguments
>  - trailers: add data structures and basic functions
>
>  A new filter to programatically edit the tail end of the commit log
>  messages.
>
>  Will merge to 'next'.

I have a new version of this series, but I am not very happy with it.
Especially, I am not very happy about not using strcasecmp() and
instead lowercasing some parameters read from the config file.
That's because it adds some lines and one more patch as I feel that I
have to refactor lowercasing functions.

I will send this new series soon anyway and we can choose if we want
these lowercasing changes or not.

Thanks,
Christian.
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v2 000/142] Use the $( ... ) construct for command substitution instead of using the back-quotes

2014-03-26 Thread Elia Pinto
2014-03-26 8:44 GMT+01:00 Eric Sunshine :
> On Wed, Mar 26, 2014 at 3:02 AM, Matthieu Moy
>  wrote:
>> Junio C Hamano  writes:
>>
>>>  - Nobody has time or energy to go through 140+ patches in one go,
>>>with enough concentration necessary to do so without making
>>>mistakes (this applies to yourself, too---producing mechanical
>>>replacement is a no-cost thing, finding mistakes in mechanical
>>>replacement takes real effort).
>>
>> It's a bit less bad than it seems:
>>
>>  142 files changed, 609 insertions(+), 609 deletions(-)
>>
>> The first pass I did was a very quick one, but I already went through
>> the patches I received (apparently not the whole series) and it wasn't
>> that long.
>
> I also gave v2 a read-through. Nothing jumped out as a red-flag.

Thank you all. I will change the comment as  the maintainer wishes
(75ee3d7078fbcc3b87a3ae5e0cf42f46256c5da4 for example) and send the
other patches slowly (10 at a time every week, boring but that's
okay).

Best Regards
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [RFC/PATCH 1/4] test-lib: add test_dir_is_empty()

2014-03-26 Thread Michael Haggerty
On 03/26/2014 09:29 AM, Jens Lehmann wrote:
> Am 25.03.2014 21:49, schrieb Junio C Hamano:
>> Jens Lehmann  writes:
>>
>>> For the upcoming submodule test framework we often need to assert that an
>>> empty directory exists in the work tree. Add the test_dir_is_empty()
>>> function which asserts that the given argument is an empty directory.
>>>
>>> Signed-off-by: Jens Lehmann 
>>> ---
>>>
>>> I believe this one is pretty straightforward (unless I missed that this
>>> functionality already exists someplace I forgot to look ;-).
>>
>> I am not very thrilled to see that it depends on "." and ".." to
>> always exist, which may be true for all POSIX filesystems, but
>> still...
> 
> Agreed. I didn't find any one-liners to do that ("ls -A" isn't
> POSIX), so I decided to wrap that in a function. Testing that
> "rmdir" on the directory succeeds (because the directory is
> empty) would kinda work, but then we'd have to re-create the
> directory afterwards, which really doesn't sound like a good
> strategy either as the test would manipulate the to-be-tested
> object. I'm not terribly happy with depending on "." and ".."
> either, but couldn't come up with something better. At least
> the test should fail for any filesystem not having the dot
> files ...
> 
>> Do expected callsites of this helper care if "$1" is a symbolic link
>> that points at an empty directory?
> 
> Yep, a symbolic link pointing to an empty directory should make
> the test fail.
> 
>> What do expected callsites really want to ensure?  In other words,
>> why do they care if the directory is empty?  Is it to make sure,
>> after some operation, they can "rmdir" the directory?
> 
> To assert that a submodule is created but *not* populated. This
> is intended to catch any possible fallout from the recursive
> checkout later, in case that would kick in when it shouldn't.
> 
>>>  t/test-lib-functions.sh | 11 +++
>>>  1 file changed, 11 insertions(+)
>>>
>>> diff --git a/t/test-lib-functions.sh b/t/test-lib-functions.sh
>>> index 158e10a..93d10cd 100644
>>> --- a/t/test-lib-functions.sh
>>> +++ b/t/test-lib-functions.sh
>>> @@ -489,6 +489,17 @@ test_path_is_dir () {
>>> fi
>>>  }
>>>
>>> +# Check if the directory exists and is empty as expected, barf otherwise.
>>> +test_dir_is_empty () {
>>> +   test_path_is_dir "$1" &&
>>> +   if test $(ls -a1 "$1" | wc -l) != 2
>>> +   then
>>> +   echo "Directory '$1' is not empty, it contains:"
>>> +   ls -la "$1"
>>> +   return 1
>>> +   fi
>>> +}
>>> +
>>>  test_path_is_missing () {
>>> if [ -e "$1" ]
>>> then

Why not do something like

test -z "$(ls -a1 "$1" | egrep -v '^\.\.?$')"

I.e., make the test ignore "." and ".." without depending on their
existence?

Michael

-- 
Michael Haggerty
mhag...@alum.mit.edu
http://softwareswirl.blogspot.com/
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 5/5] log: do not segfault on gmtime errors

2014-03-26 Thread Charles Bailey
On Mon, Feb 24, 2014 at 02:49:05AM -0500, Jeff King wrote:
> +# date is within 2^63-1, but enough to choke glibc's gmtime
> +test_expect_success 'absurdly far-in-future dates produce sentinel' '
> + commit=$(munge_author_date HEAD 99) &&
> + echo "Thu Jan 1 00:00:00 1970 +" >expect &&
> + git log -1 --format=%ad $commit >actual &&
> + test_cmp expect actual
> +'

Git on AIX seems happy to convert this to Thu Oct 24 18:46:39
162396404 -0700. I don't know if this is correct for the given input
but the test fails.

Charles.
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v2 001/142] check-builtins.sh: use the $( ... ) construct for command substitution

2014-03-26 Thread David Kastrup
Junio C Hamano  writes:

> Elia Pinto  writes:
>
>> The Git CodingGuidelines prefer the $( ... ) construct for command
>> substitution instead of using the back-quotes, or grave accents (`..`).
>>
>> The backquoted form is the historical method for command substitution,
>> and is supported by POSIX. However, all but the simplest uses become
>> complicated quickly. In particular, embedded command substitutions
>> and/or the use of double quotes require careful escaping with the backslash
>> character. Because of this the POSIX shell adopted the $(…) feature from
>> the Korn shell.
>>
>> The patch was generated by the simple script
>>
>> for _f in $(find . -name "*.sh")
>> do
>>   sed -i 's@`\(.*\)`@$(\1)@g' ${_f}
>> done
>
> "and then carefully proofread" is sorely needed here.

It would already help to skip comment lines.

-- 
David Kastrup
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [RFC/PATCH 1/4] test-lib: add test_dir_is_empty()

2014-03-26 Thread David Kastrup
Junio C Hamano  writes:

> Jens Lehmann  writes:
>
>> For the upcoming submodule test framework we often need to assert that an
>> empty directory exists in the work tree. Add the test_dir_is_empty()
>> function which asserts that the given argument is an empty directory.
>>
>> Signed-off-by: Jens Lehmann 
>> ---
>>
>> I believe this one is pretty straightforward (unless I missed that this
>> functionality already exists someplace I forgot to look ;-).
>
> I am not very thrilled to see that it depends on "." and ".." to
> always exist, which may be true for all POSIX filesystems, but
> still...

Not even there, though few people will likely use / as their work
tree...

-- 
David Kastrup
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v2 001/142] check-builtins.sh: use the $( ... ) construct for command substitution

2014-03-26 Thread Matthieu Moy
David Kastrup  writes:

> Junio C Hamano  writes:
>
>> Elia Pinto  writes:
>>
>>> The Git CodingGuidelines prefer the $( ... ) construct for command
>>> substitution instead of using the back-quotes, or grave accents (`..`).
>>>
>>> The backquoted form is the historical method for command substitution,
>>> and is supported by POSIX. However, all but the simplest uses become
>>> complicated quickly. In particular, embedded command substitutions
>>> and/or the use of double quotes require careful escaping with the backslash
>>> character. Because of this the POSIX shell adopted the $(…) feature from
>>> the Korn shell.
>>>
>>> The patch was generated by the simple script
>>>
>>> for _f in $(find . -name "*.sh")
>>> do
>>>   sed -i 's@`\(.*\)`@$(\1)@g' ${_f}
>>> done
>>
>> "and then carefully proofread" is sorely needed here.
>
> It would already help to skip comment lines.

Actually no: most comments including `...` are code examples that we
want to fix too, except 3 instances (see my other message).

-- 
Matthieu Moy
http://www-verimag.imag.fr/~moy/
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: Borrowing objects from nearby repositories

2014-03-26 Thread Andrew Keller
On Mar 25, 2014, at 6:17 PM, Junio C Hamano  wrote:

> Junio C Hamano  writes:
> 
>> Ævar Arnfjörð Bjarmason  writes:
>> 
 1) Introduce '--borrow' to `git-fetch`.  This would behave similarly
>>> to '--reference', except that it operates on a temporary basis, and
>>> does not assume that the reference repository will exist after the
>>> operation completes, so any used objects are copied into the local
>>> objects database.  In theory, this mechanism would be distinct from
>>> --reference', so if both are used, some objects would be copied, and
>>> some objects would be accessible via a reference repository referenced
>>> by the alternates file.
>>> 
>>> Isn't this the same as git clone --reference  --no-hardlinks
>>>  ?
>>> 
>>> Also without --no-hardlinks we're not assuming that the other repo
>>> doesn't go away (you could rm-rf it), just that the files won't be
>>> *modified*, which Git won't do, but you could manually do with other
>>> tools, so the default is to hardlink.
>> 
>> I think that the standard practice with the existing toolset is to
>> clone with reference and then repack.  That is:
>> 
>>$ git clone --reference  git://over/there mine
>>$ cd mine
>>$ git repack -a -d
>> 
>> And then you can try this:
>> 
>>$ mv .git/objects/info/alternates .git/objects/info/alternates.disabled
>>$ git fsck
>> 
>> to make sure that you are no longer borrowing anything from the
>> borrowee.  Once you are satisfied, you can remove the saved-away
>> alternates.disabled file.
> 
> Oh, I forgot to say that I am not opposed if somebody wants to teach
> "git clone" a new option to copy its objects from two places,
> (hopefully) the majority from near-by reference repository and the
> remainder over the network, without permanently relying on the
> former via the alternates mechanism.  The implementation of such a
> feature could even literally be "clone with reference first and then
> repack" at least initially but even in the final version.

That was actually one of my first ideas - adding some sort of '--auto-repack' 
option to git-clone.  It's a relatively small change, and would work.  However, 
keeping in mind my end goal of automating the feature to the point where you 
could run simply 'git clone ', an '--auto-repack' option is more difficult 
to undo.  You would need a new parameter to disable the automatic adding of 
reference repositories, and a new parameter to undo '--auto-repack', and you'd 
have to remember to actually undo both of those settings.

In contrast, if the new feature was '--borrow', and the evolution of the 
feature was a global configuration 'fetch.autoBorrow', then to turn it off 
temporarily, one only needs a single new parameter '--no-auto-borrow'.  I think 
this is a cleaner approach than the former, although much more work.

Thanks,
 - Andrew Keller

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 00/17] git-ls

2014-03-26 Thread Nguyễn Thái Ngọc Duy
Compared to v1, git-ls now does not accept ls-files options (previous
git-ls is more like an alias of ls-files). I want this because ls may
take a different set of options than ls-files. Most functionality is
shared so if you're not happy with ls, you can fall back to ls-files.

New alias options are supported, -1 == --no-column, -R ==
--max-depth=-1. If more than one file criteria is chosen (e.g. "ls -cmo")
then --tag is implied. File order is fixed ("ls-files -cmo" actually
shows two or three separate listings, "ls -cmo" shows one sorted
listing). It also shows directories from the index.

Documentation is there. No tests yet because the behavior may still
need some polishing.

Nguyễn Thái Ngọc Duy (17):
  ls_colors.c: add $LS_COLORS parsing code
  ls_colors.c: parse color.ls.* from config file
  ls_colors.c: add function to color a file name
  ls_colors.c: highlight submodules like directories
  ls-files: buffer full item in strbuf before printing
  ls-files: add --color to highlight file names
  ls-files: add --column
  ls-files: support --max-depth
  ls-files: split main ls-files logic into ls_files() function
  Add git-ls, a user friendly version of ls-files and more
  ls: -u does not imply showing stages
  ls: add -R/--recursive short for --max-depth=-1
  ls: add -1 short for --no-column in the spirit of GNU ls
  ls: add -t back
  ls: sort output and remove duplicates
  ls: do not show duplicate cached entries
  ls: show directories as well as files

 .gitignore |   1 +
 Documentation/config.txt   |  22 ++
 Documentation/git-ls-files.txt |  22 ++
 Documentation/git-ls.txt (new) |  95 
 Makefile   |   2 +
 builtin.h  |   1 +
 builtin/ls-files.c | 446 +---
 color.h|  10 +
 command-list.txt   |   1 +
 git.c  |   1 +
 ls_colors.c (new)  | 496 +
 11 files changed, 1012 insertions(+), 85 deletions(-)
 create mode 100644 Documentation/git-ls.txt
 create mode 100644 ls_colors.c

-- 
1.9.1.345.ga1a145c

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 02/17] ls_colors.c: parse color.ls.* from config file

2014-03-26 Thread Nguyễn Thái Ngọc Duy
This is the second (and preferred) source for color information. This
will override $LS_COLORS.

Signed-off-by: Nguyễn Thái Ngọc Duy 
---
 Documentation/config.txt | 11 +++
 ls_colors.c  | 26 ++
 2 files changed, 37 insertions(+)

diff --git a/Documentation/config.txt b/Documentation/config.txt
index 73c8973..3fb754e 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -909,6 +909,17 @@ color.status.::
to red). The values of these variables may be specified as in
color.branch..
 
+color.ls.::
+   Use customized color for file name colorization. If not set
+   and the environment variable LS_COLORS is set, color settings
+   from $LS_COLORS are used. `` can be `normal`, `file`,
+   `directory`, `symlink`, `fifo`, `socket`, `block`, `char`,
+   `missing`, `orphan`, `executable`, `door`, `setuid`, `setgid`,
+   `sticky`, `otherwritable`, `stickyotherwritable`, `cap`,
+   `multihardlink`. The values of these variables may be
+   specified as in color.branch..
+
+
 color.ui::
This variable determines the default value for variables such
as `color.diff` and `color.grep` that control the use of color
diff --git a/ls_colors.c b/ls_colors.c
index eb944f4..cef5a92 100644
--- a/ls_colors.c
+++ b/ls_colors.c
@@ -68,6 +68,14 @@ static const char *const indicator_name[] = {
NULL
 };
 
+static const char* const config_name[] = {
+   "", "", "", "", "normal", "file", "directory", "symlink",
+   "fifo", "socket", "block", "char", "missing", "orphan", "executable",
+   "door", "setuid", "setgid", "sticky", "otherwritable",
+   "stickyotherwritable", "cap", "multihardlink", "",
+   NULL
+};
+
 struct bin_str {
size_t len; /* Number of bytes */
const char *string; /* Pointer to the same */
@@ -285,6 +293,23 @@ static int get_funky_string(char **dest, const char **src, 
int equals_end,
return state != ST_ERROR;
 }
 
+static int ls_colors_config(const char *var, const char *value, void *cb)
+{
+   int slot;
+   if (!starts_with(var, "color.ls."))
+   return 0;
+   var += 9;
+   for (slot = 0; config_name[slot]; slot++)
+   if (!strcasecmp(var, config_name[slot]))
+   break;
+   if (!config_name[slot])
+   return 0;
+   if (!value)
+   return config_error_nonbool(var);
+   color_parse(value, var, ls_colors[slot]);
+   return 0;
+}
+
 void parse_ls_color(void)
 {
const char *p;  /* Pointer to character being parsed */
@@ -395,4 +420,5 @@ void parse_ls_color(void)
 
if (!strcmp(ls_colors[LS_LN], "target"))
color_symlink_as_referent = 1;
+   git_config(ls_colors_config, NULL);
 }
-- 
1.9.1.345.ga1a145c

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 04/17] ls_colors.c: highlight submodules like directories

2014-03-26 Thread Nguyễn Thái Ngọc Duy
Signed-off-by: Nguyễn Thái Ngọc Duy 
---
 Documentation/config.txt | 3 ++-
 ls_colors.c  | 8 +++-
 2 files changed, 9 insertions(+), 2 deletions(-)

diff --git a/Documentation/config.txt b/Documentation/config.txt
index 3fb754e..6bca55e 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -913,7 +913,8 @@ color.ls.::
Use customized color for file name colorization. If not set
and the environment variable LS_COLORS is set, color settings
from $LS_COLORS are used. `` can be `normal`, `file`,
-   `directory`, `symlink`, `fifo`, `socket`, `block`, `char`,
+   `directory`, `submodule`,
+   `symlink`, `fifo`, `socket`, `block`, `char`,
`missing`, `orphan`, `executable`, `door`, `setuid`, `setgid`,
`sticky`, `otherwritable`, `stickyotherwritable`, `cap`,
`multihardlink`. The values of these variables may be
diff --git a/ls_colors.c b/ls_colors.c
index 1125329..0cc4e9b 100644
--- a/ls_colors.c
+++ b/ls_colors.c
@@ -29,6 +29,8 @@ enum color_ls {
LS_MH,  /* multi hardlink */
LS_CL,  /* clear end of line */
 
+   LS_SUBMODULE,
+
MAX_LS
 };
 
@@ -58,7 +60,8 @@ static char ls_colors[MAX_LS][COLOR_MAXLEN] = {
GIT_COLOR_BLACK_ON_GREEN,
"",
"",
-   ""
+   "",
+   GIT_COLOR_BOLD_BLUE
 };
 
 static const char *const indicator_name[] = {
@@ -73,6 +76,7 @@ static const char* const config_name[] = {
"fifo", "socket", "block", "char", "missing", "orphan", "executable",
"door", "setuid", "setgid", "sticky", "otherwritable",
"stickyotherwritable", "cap", "multihardlink", "",
+   "submodule",
NULL
 };
 
@@ -448,6 +452,8 @@ void color_filename(struct strbuf *sb, const char *name,
type = LS_DI;
} else if (S_ISLNK (mode))
type = (!linkok && *ls_colors[LS_OR]) ? LS_OR : LS_LN;
+   else if (S_ISGITLINK(mode))
+   type = LS_SUBMODULE;
else if (S_ISFIFO (mode))
type = LS_PI;
else if (S_ISSOCK (mode))
-- 
1.9.1.345.ga1a145c

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 01/17] ls_colors.c: add $LS_COLORS parsing code

2014-03-26 Thread Nguyễn Thái Ngọc Duy
Reusing color settings from $LS_COLORS could give a native look and
feel on file coloring.

This code is basically from coreutils.git [1], rewritten to fit Git.

As this is from GNU ls, the environment variable CLICOLOR is not
tested. It is to be decided later whether we should ignore $LS_COLORS
if $CLICOLOR is not set on Mac or FreeBSD.

[1] commit 7326d1f1a67edf21947ae98194f98c38b6e9e527 file
src/ls.c. This is the last GPL-2 commit before coreutils turns to
GPL-3.

Signed-off-by: Nguyễn Thái Ngọc Duy 
---
 Makefile  |   1 +
 color.h   |   8 ++
 ls_colors.c (new) | 398 ++
 3 files changed, 407 insertions(+)
 create mode 100644 ls_colors.c

diff --git a/Makefile b/Makefile
index f818eec..f6a6e14 100644
--- a/Makefile
+++ b/Makefile
@@ -819,6 +819,7 @@ LIB_OBJS += list-objects.o
 LIB_OBJS += ll-merge.o
 LIB_OBJS += lockfile.o
 LIB_OBJS += log-tree.o
+LIB_OBJS += ls_colors.o
 LIB_OBJS += mailmap.o
 LIB_OBJS += match-trees.o
 LIB_OBJS += merge.o
diff --git a/color.h b/color.h
index 9a8495b..640fc48 100644
--- a/color.h
+++ b/color.h
@@ -45,6 +45,12 @@ struct strbuf;
 #define GIT_COLOR_BG_MAGENTA   "\033[45m"
 #define GIT_COLOR_BG_CYAN  "\033[46m"
 
+#define GIT_COLOR_WHITE_ON_RED"\033[37;41m"
+#define GIT_COLOR_WHITE_ON_BLUE   "\033[37;44m"
+#define GIT_COLOR_BLACK_ON_YELLOW "\033[30;43m"
+#define GIT_COLOR_BLUE_ON_GREEN   "\033[34;42m"
+#define GIT_COLOR_BLACK_ON_GREEN  "\033[30;42m"
+
 /* A special value meaning "no color selected" */
 #define GIT_COLOR_NIL "NIL"
 
@@ -87,4 +93,6 @@ void color_print_strbuf(FILE *fp, const char *color, const 
struct strbuf *sb);
 
 int color_is_nil(const char *color);
 
+void parse_ls_color(void);
+
 #endif /* COLOR_H */
diff --git a/ls_colors.c b/ls_colors.c
new file mode 100644
index 000..eb944f4
--- /dev/null
+++ b/ls_colors.c
@@ -0,0 +1,398 @@
+#include "cache.h"
+#include "color.h"
+
+enum color_ls {
+   LS_LC,  /* left, unused */
+   LS_RC,  /* right, unused */
+   LS_EC,  /* end color, unused */
+   LS_RS,  /* reset */
+   LS_NO,  /* normal */
+   LS_FL,  /* file, default */
+   LS_DI,  /* directory */
+   LS_LN,  /* symlink */
+
+   LS_PI,  /* pipe */
+   LS_SO,  /* socket */
+   LS_BD,  /* block device */
+   LS_CD,  /* char device */
+   LS_MI,  /* missing file */
+   LS_OR,  /* orphaned symlink */
+   LS_EX,  /* executable */
+   LS_DO,  /* Solaris door */
+
+   LS_SU,  /* setuid */
+   LS_SG,  /* setgid */
+   LS_ST,  /* sticky */
+   LS_OW,  /* other-writable */
+   LS_TW,  /* ow with sticky */
+   LS_CA,  /* cap */
+   LS_MH,  /* multi hardlink */
+   LS_CL,  /* clear end of line */
+
+   MAX_LS
+};
+
+static char ls_colors[MAX_LS][COLOR_MAXLEN] = {
+   "",
+   "",
+   "",
+   GIT_COLOR_RESET,
+   GIT_COLOR_NORMAL,
+   GIT_COLOR_NORMAL,
+   GIT_COLOR_BOLD_BLUE,
+   GIT_COLOR_BOLD_CYAN,
+
+   GIT_COLOR_YELLOW,
+   GIT_COLOR_BOLD_MAGENTA,
+   GIT_COLOR_BOLD_YELLOW,
+   GIT_COLOR_BOLD_YELLOW,
+   GIT_COLOR_NORMAL,
+   GIT_COLOR_NORMAL,
+   GIT_COLOR_BOLD_GREEN,
+   GIT_COLOR_BOLD_MAGENTA,
+
+   GIT_COLOR_WHITE_ON_RED,
+   GIT_COLOR_BLACK_ON_YELLOW,
+   GIT_COLOR_WHITE_ON_BLUE,
+   GIT_COLOR_BLUE_ON_GREEN,
+   GIT_COLOR_BLACK_ON_GREEN,
+   "",
+   "",
+   ""
+};
+
+static const char *const indicator_name[] = {
+   "lc", "rc", "ec", "rs", "no", "fi", "di", "ln",
+   "pi", "so", "bd", "cd", "mi", "or", "ex", "do",
+   "su", "sg", "st", "ow", "tw", "ca", "mh", "cl",
+   NULL
+};
+
+struct bin_str {
+   size_t len; /* Number of bytes */
+   const char *string; /* Pointer to the same */
+};
+
+struct color_ext_type {
+   struct bin_str ext; /* The extension we're looking for */
+   struct bin_str seq; /* The sequence to output when we do */
+   struct color_ext_type *next;/* Next in list */
+};
+
+static struct color_ext_type *color_ext_list = NULL;
+
+/*
+ * When true, in a color listing, color each symlink name according to the
+ * type of file it points to.  Otherwise, color them according to the `ln'
+ * directive in LS_COLORS.  Dangling (orphan) symlinks are treated specially,
+ * regardless.  This is set when `ln=target' appears in LS_COLORS.
+ */
+static int color_symlink_as_referent;
+
+/*
+ * Parse a string as part of the LS_COLORS variable; this may involve
+ * decoding all kinds of escape characters.  If equal

[PATCH v2 06/17] ls-files: add --color to highlight file names

2014-03-26 Thread Nguyễn Thái Ngọc Duy
Signed-off-by: Nguyễn Thái Ngọc Duy 
---
 Documentation/git-ls-files.txt |  9 +
 builtin/ls-files.c | 38 +++---
 2 files changed, 44 insertions(+), 3 deletions(-)

diff --git a/Documentation/git-ls-files.txt b/Documentation/git-ls-files.txt
index c0856a6..5c1b7f3 100644
--- a/Documentation/git-ls-files.txt
+++ b/Documentation/git-ls-files.txt
@@ -147,6 +147,15 @@ a space) at the start of each line:
possible for manual inspection; the exact format may change at
any time.
 
+--color[=]::
+   Color file names. The value must be always (default), never,
+   or auto.
+
+--no-color::
+   Turn off coloring, even when the configuration file gives the
+   default to color output, same as `--color=never`. This is the
+   default.
+
 \--::
Do not interpret any more arguments as options.
 
diff --git a/builtin/ls-files.c b/builtin/ls-files.c
index 6e30592..2857b38 100644
--- a/builtin/ls-files.c
+++ b/builtin/ls-files.c
@@ -14,6 +14,7 @@
 #include "resolve-undo.h"
 #include "string-list.h"
 #include "pathspec.h"
+#include "color.h"
 
 static int abbrev;
 static int show_deleted;
@@ -27,6 +28,7 @@ static int show_killed;
 static int show_valid_bit;
 static int line_terminator = '\n';
 static int debug_mode;
+static int use_color;
 
 static const char *prefix;
 static int max_prefix_len;
@@ -60,7 +62,6 @@ static void write_name(struct strbuf *sb, const char *name)
strbuf_release(&sb2);
} else
quote_path_relative(name, real_prefix, sb);
-   strbuf_addch(sb, line_terminator);
 }
 
 static void strbuf_fputs(struct strbuf *sb, FILE *fp)
@@ -68,6 +69,21 @@ static void strbuf_fputs(struct strbuf *sb, FILE *fp)
fwrite(sb->buf, sb->len, 1, fp);
 }
 
+static void write_dir_entry(struct strbuf *sb, const struct dir_entry *ent)
+{
+   struct strbuf quoted = STRBUF_INIT;
+   struct stat st;
+   if (stat(ent->name, &st))
+   st.st_mode = 0;
+   write_name("ed, ent->name);
+   if (want_color(use_color))
+   color_filename(sb, ent->name, quoted.buf, st.st_mode, 1);
+   else
+   strbuf_addbuf(sb, "ed);
+   strbuf_addch(sb, line_terminator);
+   strbuf_release("ed);
+}
+
 static void show_dir_entry(const char *tag, struct dir_entry *ent)
 {
static struct strbuf sb = STRBUF_INIT;
@@ -81,7 +97,7 @@ static void show_dir_entry(const char *tag, struct dir_entry 
*ent)
 
strbuf_reset(&sb);
strbuf_addstr(&sb, tag);
-   write_name(&sb, ent->name);
+   write_dir_entry(&sb, ent);
strbuf_fputs(&sb, stdout);
 }
 
@@ -146,6 +162,18 @@ static void show_killed_files(struct dir_struct *dir)
}
 }
 
+static void write_ce_name(struct strbuf *sb, const struct cache_entry *ce)
+{
+   struct strbuf quoted = STRBUF_INIT;
+   write_name("ed, ce->name);
+   if (want_color(use_color))
+   color_filename(sb, ce->name, quoted.buf, ce->ce_mode, 1);
+   else
+   strbuf_addbuf(sb, "ed);
+   strbuf_addch(sb, line_terminator);
+   strbuf_release("ed);
+}
+
 static void show_ce_entry(const char *tag, const struct cache_entry *ce)
 {
static struct strbuf sb = STRBUF_INIT;
@@ -186,7 +214,7 @@ static void show_ce_entry(const char *tag, const struct 
cache_entry *ce)
find_unique_abbrev(ce->sha1,abbrev),
ce_stage(ce));
}
-   write_name(&sb, ce->name);
+   write_ce_name(&sb, ce);
strbuf_fputs(&sb, stdout);
if (debug_mode) {
const struct stat_data *sd = &ce->ce_stat_data;
@@ -523,6 +551,7 @@ int cmd_ls_files(int argc, const char **argv, const char 
*cmd_prefix)
N_("if any  is not in the index, treat this as an 
error")),
OPT_STRING(0, "with-tree", &with_tree, N_("tree-ish"),
N_("pretend that paths removed since  are 
still present")),
+   OPT__COLOR(&use_color, N_("show color")),
OPT__ABBREV(&abbrev),
OPT_BOOL(0, "debug", &debug_mode, N_("show debugging data")),
OPT_END()
@@ -570,6 +599,9 @@ int cmd_ls_files(int argc, const char **argv, const char 
*cmd_prefix)
if (require_work_tree && !is_inside_work_tree())
setup_work_tree();
 
+   if (want_color(use_color))
+   parse_ls_color();
+
parse_pathspec(&pathspec, 0,
   PATHSPEC_PREFER_CWD |
   PATHSPEC_STRIP_SUBMODULE_SLASH_CHEAP,
-- 
1.9.1.345.ga1a145c

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 05/17] ls-files: buffer full item in strbuf before printing

2014-03-26 Thread Nguyễn Thái Ngọc Duy
Buffering so that we can manipulate the strings (e.g. coloring)
further before finally printing them.

Signed-off-by: Nguyễn Thái Ngọc Duy 
---
 builtin/ls-files.c | 48 +++-
 1 file changed, 35 insertions(+), 13 deletions(-)

diff --git a/builtin/ls-files.c b/builtin/ls-files.c
index 47c3880..6e30592 100644
--- a/builtin/ls-files.c
+++ b/builtin/ls-files.c
@@ -47,18 +47,30 @@ static const char *tag_modified = "";
 static const char *tag_skip_worktree = "";
 static const char *tag_resolve_undo = "";
 
-static void write_name(const char *name)
+static void write_name(struct strbuf *sb, const char *name)
 {
/*
 * With "--full-name", prefix_len=0; this caller needs to pass
 * an empty string in that case (a NULL is good for "").
 */
-   write_name_quoted_relative(name, prefix_len ? prefix : NULL,
-  stdout, line_terminator);
+   const char *real_prefix = prefix_len ? prefix : NULL;
+   if (!line_terminator) {
+   struct strbuf sb2 = STRBUF_INIT;
+   strbuf_addstr(sb, relative_path(name, real_prefix, &sb2));
+   strbuf_release(&sb2);
+   } else
+   quote_path_relative(name, real_prefix, sb);
+   strbuf_addch(sb, line_terminator);
+}
+
+static void strbuf_fputs(struct strbuf *sb, FILE *fp)
+{
+   fwrite(sb->buf, sb->len, 1, fp);
 }
 
 static void show_dir_entry(const char *tag, struct dir_entry *ent)
 {
+   static struct strbuf sb = STRBUF_INIT;
int len = max_prefix_len;
 
if (len >= ent->len)
@@ -67,8 +79,10 @@ static void show_dir_entry(const char *tag, struct dir_entry 
*ent)
if (!dir_path_match(ent, &pathspec, len, ps_matched))
return;
 
-   fputs(tag, stdout);
-   write_name(ent->name);
+   strbuf_reset(&sb);
+   strbuf_addstr(&sb, tag);
+   write_name(&sb, ent->name);
+   strbuf_fputs(&sb, stdout);
 }
 
 static void show_other_files(struct dir_struct *dir)
@@ -134,6 +148,7 @@ static void show_killed_files(struct dir_struct *dir)
 
 static void show_ce_entry(const char *tag, const struct cache_entry *ce)
 {
+   static struct strbuf sb = STRBUF_INIT;
int len = max_prefix_len;
 
if (len >= ce_namelen(ce))
@@ -161,16 +176,18 @@ static void show_ce_entry(const char *tag, const struct 
cache_entry *ce)
tag = alttag;
}
 
+   strbuf_reset(&sb);
if (!show_stage) {
-   fputs(tag, stdout);
+   strbuf_addstr(&sb, tag);
} else {
-   printf("%s%06o %s %d\t",
-  tag,
-  ce->ce_mode,
-  find_unique_abbrev(ce->sha1,abbrev),
-  ce_stage(ce));
+   strbuf_addf(&sb, "%s%06o %s %d\t",
+   tag,
+   ce->ce_mode,
+   find_unique_abbrev(ce->sha1,abbrev),
+   ce_stage(ce));
}
-   write_name(ce->name);
+   write_name(&sb, ce->name);
+   strbuf_fputs(&sb, stdout);
if (debug_mode) {
const struct stat_data *sd = &ce->ce_stat_data;
 
@@ -206,7 +223,12 @@ static void show_ru_info(void)
printf("%s%06o %s %d\t", tag_resolve_undo, ui->mode[i],
   find_unique_abbrev(ui->sha1[i], abbrev),
   i + 1);
-   write_name(path);
+   /*
+* With "--full-name", prefix_len=0; this caller needs 
to pass
+* an empty string in that case (a NULL is good for "").
+*/
+   write_name_quoted_relative(path, prefix_len ? prefix : 
NULL,
+  stdout, line_terminator);
}
}
 }
-- 
1.9.1.345.ga1a145c

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 10/17] Add git-ls, a user friendly version of ls-files and more

2014-03-26 Thread Nguyễn Thái Ngọc Duy
This is more user friendly version of ls-files:

* it's automatically colored and columnized
* it refreshes the index like all porcelain commands
* it defaults to non-recursive behavior like ls
* :(glob) is on by default so '*.c' means a.c but not a/b.c, use
  '**/*.c' for that.
* auto pager

Signed-off-by: Nguyễn Thái Ngọc Duy 
---
 .gitignore |  1 +
 Documentation/config.txt   | 10 ++
 Documentation/git-ls.txt (new) | 82 ++
 Makefile   |  1 +
 builtin.h  |  1 +
 builtin/ls-files.c | 70 
 command-list.txt   |  1 +
 git.c  |  1 +
 8 files changed, 167 insertions(+)
 create mode 100644 Documentation/git-ls.txt

diff --git a/.gitignore b/.gitignore
index dc600f9..f91af81 100644
--- a/.gitignore
+++ b/.gitignore
@@ -76,6 +76,7 @@
 /git-init-db
 /git-instaweb
 /git-log
+/git-ls
 /git-ls-files
 /git-ls-remote
 /git-ls-tree
diff --git a/Documentation/config.txt b/Documentation/config.txt
index 6bca55e..87a6dcf 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -909,6 +909,12 @@ color.status.::
to red). The values of these variables may be specified as in
color.branch..
 
+color.ls::
+   A boolean to enable/disable color in the output of
+   linkgit:git-ls[1]. May be set to `always`, `false` (or
+   `never`) or `auto` (or `true`), in which case colors are used
+   only when the output is to a terminal. Defaults to false.
+
 color.ls.::
Use customized color for file name colorization. If not set
and the environment variable LS_COLORS is set, color settings
@@ -981,6 +987,10 @@ column.clean::
Specify the layout when list items in `git clean -i`, which always
shows files and directories in columns. See `column.ui` for details.
 
+column.ls::
+   Specify whether to output tag listing in `git ls` in columns.
+   See `column.ui` for details.
+
 column.status::
Specify whether to output untracked files in `git status` in columns.
See `column.ui` for details.
diff --git a/Documentation/git-ls.txt b/Documentation/git-ls.txt
new file mode 100644
index 000..67ca522
--- /dev/null
+++ b/Documentation/git-ls.txt
@@ -0,0 +1,82 @@
+git-ls(1)
+===
+
+NAME
+
+git-ls - List files
+
+SYNOPSIS
+
+[verse]
+'git ls' (--[cached|deleted|others|ignored|unmerged|modified])*
+   (-[c|d|o|i|s|u|m])*
+   [options] [...]
+
+DESCRIPTION
+---
+List files (by default in current working directory) that are in the
+index. Depending on the chosen options, maybe only modified files in
+working tree are shown, or untracked files...
+
+OPTIONS
+---
+-c::
+--cached::
+   Show cached files in the output (default)
+
+-d::
+--deleted::
+   Show deleted files in the output
+
+-m::
+--modified::
+   Show modified files in the output
+
+-o::
+--others::
+   Show other (i.e. untracked) files in the output
+
+-i::
+--ignored::
+   Show only ignored files in the output. When showing files in the
+   index, print only those matched by an exclude pattern. When
+   showing "other" files, show only those matched by an exclude
+   pattern.
+
+-u::
+--unmerged::
+   Show unmerged files in the output (forces --stage)
+
+--color[=]::
+   Color file names. The value must be always (default), never,
+   or auto.
+
+--no-color::
+   Turn off coloring, even when the configuration file gives the
+   default to color output, same as `--color=never`. This is the
+   default.
+
+--column[=]::
+--no-column::
+   Display files in columns. See configuration variable column.ui
+   for option syntax.`--column` and `--no-column` without options
+   are equivalent to 'always' and 'never' respectively.
+
+--max-depth ::
+   For each  given on command line, descend at most 
+   levels of directories. A negative value means no limit.
+   This option is ignored if  contains active wildcards.
+   In other words if "a*" matches a directory named "a*",
+   "*" is matched literally so --max-depth is still effective.
+
+::
+   Files to show. :(glob) magic is enabled and recursion disabled
+   by default.
+
+SEE ALSO
+
+linkgit:git-ls-files[1]
+
+GIT
+---
+Part of the linkgit:git[1] suite
diff --git a/Makefile b/Makefile
index f6a6e14..b0bc40a 100644
--- a/Makefile
+++ b/Makefile
@@ -584,6 +584,7 @@ BUILT_INS += git-cherry-pick$X
 BUILT_INS += git-format-patch$X
 BUILT_INS += git-fsck-objects$X
 BUILT_INS += git-init$X
+BUILT_INS += git-ls$X
 BUILT_INS += git-merge-subtree$X
 BUILT_INS += git-show$X
 BUILT_INS += git-stage$X
diff --git a/builtin.h b/builtin.h
index c47c110..177aa7d 100644
--- a/builtin.h
+++ b/builtin.h
@@ -75,6 +75,7 @@ extern int cmd_index_pack(int argc, const char **argv, const 
char *prefix);
 extern int cmd_init_db(int argc, con

[PATCH v2 09/17] ls-files: split main ls-files logic into ls_files() function

2014-03-26 Thread Nguyễn Thái Ngọc Duy
This is a preparation step for the introduction of git-ls. "git ls"
has a different set of command line options, but it will eventually
call ls_files().

Signed-off-by: Nguyễn Thái Ngọc Duy 
---
 builtin/ls-files.c | 164 +++--
 1 file changed, 85 insertions(+), 79 deletions(-)

diff --git a/builtin/ls-files.c b/builtin/ls-files.c
index 8eef423..20ca3f2 100644
--- a/builtin/ls-files.c
+++ b/builtin/ls-files.c
@@ -31,6 +31,8 @@ static int line_terminator = '\n';
 static int debug_mode;
 static int use_color;
 static unsigned int colopts;
+static int max_depth = -1;
+static int show_tag;
 
 static const char *prefix;
 static int max_prefix_len;
@@ -42,6 +44,8 @@ static const char *with_tree;
 static int exc_given;
 static int exclude_args;
 static struct string_list output = STRING_LIST_INIT_NODUP;
+static struct dir_struct dir;
+static struct string_list exclude_list = STRING_LIST_INIT_NODUP;
 
 static const char *tag_cached = "";
 static const char *tag_unmerged = "";
@@ -500,89 +504,12 @@ static int option_parse_exclude_standard(const struct 
option *opt,
return 0;
 }
 
-int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix)
+static int ls_files(const char **argv, const char *prefix)
 {
-   int require_work_tree = 0, show_tag = 0, i;
-   int max_depth = -1;
+   int require_work_tree = 0, i;
const char *max_prefix;
-   struct dir_struct dir;
struct exclude_list *el;
-   struct string_list exclude_list = STRING_LIST_INIT_NODUP;
-   struct option builtin_ls_files_options[] = {
-   { OPTION_CALLBACK, 'z', NULL, NULL, NULL,
-   N_("paths are separated with NUL character"),
-   PARSE_OPT_NOARG, option_parse_z },
-   OPT_BOOL('t', NULL, &show_tag,
-   N_("identify the file status with tags")),
-   OPT_BOOL('v', NULL, &show_valid_bit,
-   N_("use lowercase letters for 'assume unchanged' 
files")),
-   OPT_BOOL('c', "cached", &show_cached,
-   N_("show cached files in the output (default)")),
-   OPT_BOOL('d', "deleted", &show_deleted,
-   N_("show deleted files in the output")),
-   OPT_BOOL('m', "modified", &show_modified,
-   N_("show modified files in the output")),
-   OPT_BOOL('o', "others", &show_others,
-   N_("show other files in the output")),
-   OPT_BIT('i', "ignored", &dir.flags,
-   N_("show ignored files in the output"),
-   DIR_SHOW_IGNORED),
-   OPT_BOOL('s', "stage", &show_stage,
-   N_("show staged contents' object name in the output")),
-   OPT_BOOL('k', "killed", &show_killed,
-   N_("show files on the filesystem that need to be 
removed")),
-   OPT_BIT(0, "directory", &dir.flags,
-   N_("show 'other' directories' name only"),
-   DIR_SHOW_OTHER_DIRECTORIES),
-   OPT_NEGBIT(0, "empty-directory", &dir.flags,
-   N_("don't show empty directories"),
-   DIR_HIDE_EMPTY_DIRECTORIES),
-   OPT_BOOL('u', "unmerged", &show_unmerged,
-   N_("show unmerged files in the output")),
-   OPT_BOOL(0, "resolve-undo", &show_resolve_undo,
-   N_("show resolve-undo information")),
-   { OPTION_CALLBACK, 'x', "exclude", &exclude_list, N_("pattern"),
-   N_("skip files matching pattern"),
-   0, option_parse_exclude },
-   { OPTION_CALLBACK, 'X', "exclude-from", &dir, N_("file"),
-   N_("exclude patterns are read from "),
-   0, option_parse_exclude_from },
-   OPT_STRING(0, "exclude-per-directory", &dir.exclude_per_dir, 
N_("file"),
-   N_("read additional per-directory exclude patterns in 
")),
-   { OPTION_CALLBACK, 0, "exclude-standard", &dir, NULL,
-   N_("add the standard git exclusions"),
-   PARSE_OPT_NOARG, option_parse_exclude_standard },
-   { OPTION_SET_INT, 0, "full-name", &prefix_len, NULL,
-   N_("make the output relative to the project top 
directory"),
-   PARSE_OPT_NOARG | PARSE_OPT_NONEG, NULL },
-   OPT_BOOL(0, "error-unmatch", &error_unmatch,
-   N_("if any  is not in the index, treat this as an 
error")),
-   OPT_STRING(0, "with-tree", &with_tree, N_("tree-ish"),
-   N_("pretend that paths removed since  are 
still present")),
-   OPT__COLOR(&use_color, N_("show color")),
-   OPT_COLUMN(0, "column", &colopts, N_("show files in columns")),
-  

[PATCH v2 08/17] ls-files: support --max-depth

2014-03-26 Thread Nguyễn Thái Ngọc Duy
Signed-off-by: Nguyễn Thái Ngọc Duy 
---
 Documentation/git-ls-files.txt | 7 +++
 builtin/ls-files.c | 7 +++
 2 files changed, 14 insertions(+)

diff --git a/Documentation/git-ls-files.txt b/Documentation/git-ls-files.txt
index cd52461..3c022eb 100644
--- a/Documentation/git-ls-files.txt
+++ b/Documentation/git-ls-files.txt
@@ -162,6 +162,13 @@ a space) at the start of each line:
for option syntax.`--column` and `--no-column` without options
are equivalent to 'always' and 'never' respectively.
 
+--max-depth ::
+   For each  given on command line, descend at most 
+   levels of directories. A negative value means no limit.
+   This option is ignored if  contains active wildcards.
+   In other words if "a*" matches a directory named "a*",
+   "*" is matched literally so --max-depth is still effective.
+
 \--::
Do not interpret any more arguments as options.
 
diff --git a/builtin/ls-files.c b/builtin/ls-files.c
index 335d3b0..8eef423 100644
--- a/builtin/ls-files.c
+++ b/builtin/ls-files.c
@@ -503,6 +503,7 @@ static int option_parse_exclude_standard(const struct 
option *opt,
 int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix)
 {
int require_work_tree = 0, show_tag = 0, i;
+   int max_depth = -1;
const char *max_prefix;
struct dir_struct dir;
struct exclude_list *el;
@@ -560,6 +561,9 @@ int cmd_ls_files(int argc, const char **argv, const char 
*cmd_prefix)
N_("pretend that paths removed since  are 
still present")),
OPT__COLOR(&use_color, N_("show color")),
OPT_COLUMN(0, "column", &colopts, N_("show files in columns")),
+   { OPTION_INTEGER, 0, "max-depth", &max_depth, N_("depth"),
+   N_("descend at most  levels"), PARSE_OPT_NONEG,
+   NULL, 1 },
OPT__ABBREV(&abbrev),
OPT_BOOL(0, "debug", &debug_mode, N_("show debugging data")),
OPT_END()
@@ -624,8 +628,11 @@ int cmd_ls_files(int argc, const char **argv, const char 
*cmd_prefix)
 
parse_pathspec(&pathspec, 0,
   PATHSPEC_PREFER_CWD |
+  (max_depth != -1 ? PATHSPEC_MAXDEPTH_VALID : 0) |
   PATHSPEC_STRIP_SUBMODULE_SLASH_CHEAP,
   prefix, argv);
+   pathspec.max_depth = max_depth;
+   pathspec.recursive = 1;
 
/* Find common prefix for all pathspec's */
max_prefix = common_prefix(&pathspec);
-- 
1.9.1.345.ga1a145c

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 07/17] ls-files: add --column

2014-03-26 Thread Nguyễn Thái Ngọc Duy
Signed-off-by: Nguyễn Thái Ngọc Duy 
---
 Documentation/git-ls-files.txt |  6 ++
 builtin/ls-files.c | 25 +
 2 files changed, 31 insertions(+)

diff --git a/Documentation/git-ls-files.txt b/Documentation/git-ls-files.txt
index 5c1b7f3..cd52461 100644
--- a/Documentation/git-ls-files.txt
+++ b/Documentation/git-ls-files.txt
@@ -156,6 +156,12 @@ a space) at the start of each line:
default to color output, same as `--color=never`. This is the
default.
 
+--column[=]::
+--no-column::
+   Display files in columns. See configuration variable column.ui
+   for option syntax.`--column` and `--no-column` without options
+   are equivalent to 'always' and 'never' respectively.
+
 \--::
Do not interpret any more arguments as options.
 
diff --git a/builtin/ls-files.c b/builtin/ls-files.c
index 2857b38..335d3b0 100644
--- a/builtin/ls-files.c
+++ b/builtin/ls-files.c
@@ -15,6 +15,7 @@
 #include "string-list.h"
 #include "pathspec.h"
 #include "color.h"
+#include "column.h"
 
 static int abbrev;
 static int show_deleted;
@@ -29,6 +30,7 @@ static int show_valid_bit;
 static int line_terminator = '\n';
 static int debug_mode;
 static int use_color;
+static unsigned int colopts;
 
 static const char *prefix;
 static int max_prefix_len;
@@ -39,6 +41,7 @@ static char *ps_matched;
 static const char *with_tree;
 static int exc_given;
 static int exclude_args;
+static struct string_list output = STRING_LIST_INIT_NODUP;
 
 static const char *tag_cached = "";
 static const char *tag_unmerged = "";
@@ -66,6 +69,10 @@ static void write_name(struct strbuf *sb, const char *name)
 
 static void strbuf_fputs(struct strbuf *sb, FILE *fp)
 {
+   if (column_active(colopts)) {
+   string_list_append(&output, strbuf_detach(sb, NULL));
+   return;
+   }
fwrite(sb->buf, sb->len, 1, fp);
 }
 
@@ -552,6 +559,7 @@ int cmd_ls_files(int argc, const char **argv, const char 
*cmd_prefix)
OPT_STRING(0, "with-tree", &with_tree, N_("tree-ish"),
N_("pretend that paths removed since  are 
still present")),
OPT__COLOR(&use_color, N_("show color")),
+   OPT_COLUMN(0, "column", &colopts, N_("show files in columns")),
OPT__ABBREV(&abbrev),
OPT_BOOL(0, "debug", &debug_mode, N_("show debugging data")),
OPT_END()
@@ -596,6 +604,18 @@ int cmd_ls_files(int argc, const char **argv, const char 
*cmd_prefix)
if (dir.exclude_per_dir)
exc_given = 1;
 
+   finalize_colopts(&colopts, -1);
+   if (explicitly_enable_column(colopts)) {
+   if (!line_terminator)
+   die(_("--column and -z are incompatible"));
+   if (show_resolve_undo)
+   die(_("--column and --resolve-undo are incompatible"));
+   if (debug_mode)
+   die(_("--column and --debug are incompatible"));
+   }
+   if (column_active(colopts))
+   line_terminator = 0;
+
if (require_work_tree && !is_inside_work_tree())
setup_work_tree();
 
@@ -638,6 +658,11 @@ int cmd_ls_files(int argc, const char **argv, const char 
*cmd_prefix)
if (show_resolve_undo)
show_ru_info();
 
+   if (column_active(colopts)) {
+   print_columns(&output, colopts, NULL);
+   string_list_clear(&output, 0);
+   }
+
if (ps_matched) {
int bad;
bad = report_path_error(ps_matched, &pathspec, prefix);
-- 
1.9.1.345.ga1a145c

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 11/17] ls: -u does not imply showing stages

2014-03-26 Thread Nguyễn Thái Ngọc Duy
Showing full index entry information is something for ls-files
only. The users of "git ls" may just want to know what entries are not
unmerged.

Signed-off-by: Nguyễn Thái Ngọc Duy 
---
 builtin/ls-files.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/builtin/ls-files.c b/builtin/ls-files.c
index 74eb3c2..1638983 100644
--- a/builtin/ls-files.c
+++ b/builtin/ls-files.c
@@ -527,7 +527,7 @@ static int ls_files(const char **argv, const char *prefix)
}
if (show_modified || show_others || show_deleted || (dir.flags & 
DIR_SHOW_IGNORED) || show_killed)
require_work_tree = 1;
-   if (show_unmerged)
+   if (show_unmerged && !porcelain)
/*
 * There's no point in showing unmerged unless
 * you also show the stage information.
-- 
1.9.1.345.ga1a145c

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 03/17] ls_colors.c: add function to color a file name

2014-03-26 Thread Nguyễn Thái Ngọc Duy
Tthe new function is based on print_color_indicator() from commit
7326d1f1a67edf21947ae98194f98c38b6e9e527 in coreutils.git.

Signed-off-by: Nguyễn Thái Ngọc Duy 
---
 color.h |  2 ++
 ls_colors.c | 66 +
 2 files changed, 68 insertions(+)

diff --git a/color.h b/color.h
index 640fc48..398369a 100644
--- a/color.h
+++ b/color.h
@@ -94,5 +94,7 @@ void color_print_strbuf(FILE *fp, const char *color, const 
struct strbuf *sb);
 int color_is_nil(const char *color);
 
 void parse_ls_color(void);
+void color_filename(struct strbuf *sb, const char *name,
+   const char *display_name, mode_t mode, int linkok);
 
 #endif /* COLOR_H */
diff --git a/ls_colors.c b/ls_colors.c
index cef5a92..1125329 100644
--- a/ls_colors.c
+++ b/ls_colors.c
@@ -422,3 +422,69 @@ void parse_ls_color(void)
color_symlink_as_referent = 1;
git_config(ls_colors_config, NULL);
 }
+
+void color_filename(struct strbuf *sb, const char *name,
+   const char *display_name, mode_t mode, int linkok)
+{
+   int type;
+   struct color_ext_type *ext; /* Color extension */
+
+   if (S_ISREG (mode)) {
+   type = LS_FL;
+   if ((mode & S_ISUID) != 0)
+   type = LS_SU;
+   else if ((mode & S_ISGID) != 0)
+   type = LS_SG;
+   else if ((mode & (S_IXUSR | S_IXGRP | S_IXOTH)) != 0)
+   type = LS_EX;
+   } else if (S_ISDIR (mode)) {
+   if ((mode & S_ISVTX) && (mode & S_IWOTH))
+   type = LS_TW;
+   else if ((mode & S_IWOTH) != 0)
+   type = LS_OW;
+   else if ((mode & S_ISVTX) != 0)
+   type = LS_ST;
+   else
+   type = LS_DI;
+   } else if (S_ISLNK (mode))
+   type = (!linkok && *ls_colors[LS_OR]) ? LS_OR : LS_LN;
+   else if (S_ISFIFO (mode))
+   type = LS_PI;
+   else if (S_ISSOCK (mode))
+   type = LS_SO;
+   else if (S_ISBLK (mode))
+   type = LS_BD;
+   else if (S_ISCHR (mode))
+   type = LS_CD;
+#ifdef S_ISDOOR
+   else if (S_ISDOOR (mode))
+   type = LS_DO;
+#endif
+   else
+   /* Classify a file of some other type as C_ORPHAN.  */
+   type = LS_OR;
+
+   /* Check the file's suffix only if still classified as C_FILE.  */
+   ext = NULL;
+   if (type == LS_FL) {
+   /* Test if NAME has a recognized suffix.  */
+   size_t len = strlen(name);
+   const char *p = name + len; /* Pointer to final \0. 
 */
+   for (ext = color_ext_list; ext != NULL; ext = ext->next) {
+   if (ext->ext.len <= len &&
+   !strncmp(p - ext->ext.len, ext->ext.string, 
ext->ext.len))
+   break;
+   }
+   }
+
+   if (display_name)
+   name = display_name;
+   if (ext)
+   strbuf_addf(sb, "\033[%.*sm%s%s",
+   (int)ext->seq.len, ext->seq.string,
+   name, GIT_COLOR_RESET);
+   else if (*ls_colors[type])
+   strbuf_addf(sb, "%s%s%s", ls_colors[type], name, 
GIT_COLOR_RESET);
+   else
+   strbuf_addstr(sb, name);
+}
-- 
1.9.1.345.ga1a145c

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 14/17] ls: add -t back

2014-03-26 Thread Nguyễn Thái Ngọc Duy
Tag "H" (cached) is not shown though because it's usually the majority
and becomes noise. Not showing it makes the other tags stand out. -t
is on by default if more than one file category is selected.

Signed-off-by: Nguyễn Thái Ngọc Duy 
---
 Documentation/git-ls.txt |  6 ++
 builtin/ls-files.c   | 27 +--
 2 files changed, 23 insertions(+), 10 deletions(-)

diff --git a/Documentation/git-ls.txt b/Documentation/git-ls.txt
index 0480c42..126d9db 100644
--- a/Documentation/git-ls.txt
+++ b/Documentation/git-ls.txt
@@ -47,6 +47,12 @@ OPTIONS
 --unmerged::
Show unmerged files in the output (forces --stage)
 
+-t::
+--tag::
+   Show a tag to indicate file type, helpful when multiple file
+   selections are used. See linkgit::git-ls-files[1] option `-t`
+   for more information.
+
 -R::
 --recursive::
Equivalent of --max-depth=-1 (infinite recursion).
diff --git a/builtin/ls-files.c b/builtin/ls-files.c
index 014de05..392d273 100644
--- a/builtin/ls-files.c
+++ b/builtin/ls-files.c
@@ -515,16 +515,6 @@ static int ls_files(const char **argv, const char *prefix)
for (i = 0; i < exclude_list.nr; i++) {
add_exclude(exclude_list.items[i].string, "", 0, el, 
--exclude_args);
}
-   if (show_tag || show_valid_bit) {
-   tag_cached = "H ";
-   tag_unmerged = "M ";
-   tag_removed = "R ";
-   tag_modified = "C ";
-   tag_other = "? ";
-   tag_killed = "K ";
-   tag_skip_worktree = "S ";
-   tag_resolve_undo = "U ";
-   }
if (show_modified || show_others || show_deleted || (dir.flags & 
DIR_SHOW_IGNORED) || show_killed)
require_work_tree = 1;
if (show_unmerged && !porcelain)
@@ -578,6 +568,20 @@ static int ls_files(const char **argv, const char *prefix)
  show_killed || show_modified || show_resolve_undo))
show_cached = 1;
 
+   if (show_tag == -1)
+   show_tag = (show_cached + show_deleted + show_others +
+   show_unmerged + show_killed + show_modified) > 1;
+   if (show_tag || show_valid_bit) {
+   tag_cached = porcelain ? "  " : "H ";
+   tag_unmerged = "M ";
+   tag_removed = "R ";
+   tag_modified = "C ";
+   tag_other = "? ";
+   tag_killed = "K ";
+   tag_skip_worktree = "S ";
+   tag_resolve_undo = "U ";
+   }
+
if (max_prefix)
prune_cache(max_prefix);
if (with_tree) {
@@ -727,6 +731,8 @@ int cmd_ls(int argc, const char **argv, const char 
*cmd_prefix)
N_("show unmerged files in the output")),
OPT_SET_INT('R', "recursive", &max_depth,
N_("shortcut for --max-depth=-1"), -1),
+   OPT_BOOL('t', "tag", &show_tag,
+   N_("identify the file status with tags")),
OPT__COLOR(&use_color, N_("show color")),
OPT_COLUMN(0, "column", &colopts, N_("show files in columns")),
OPT_SET_INT('1', NULL, &colopts,
@@ -756,6 +762,7 @@ int cmd_ls(int argc, const char **argv, const char 
*cmd_prefix)
setup_standard_excludes(&dir);
use_color = -1;
max_depth = 0;
+   show_tag = -1;
 
argc = parse_options(argc, argv, prefix, builtin_ls_options,
 ls_usage, 0);
-- 
1.9.1.345.ga1a145c

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 12/17] ls: add -R/--recursive short for --max-depth=-1

2014-03-26 Thread Nguyễn Thái Ngọc Duy
Signed-off-by: Nguyễn Thái Ngọc Duy 
---
 Documentation/git-ls.txt | 4 
 builtin/ls-files.c   | 2 ++
 2 files changed, 6 insertions(+)

diff --git a/Documentation/git-ls.txt b/Documentation/git-ls.txt
index 67ca522..10df6b0 100644
--- a/Documentation/git-ls.txt
+++ b/Documentation/git-ls.txt
@@ -47,6 +47,10 @@ OPTIONS
 --unmerged::
Show unmerged files in the output (forces --stage)
 
+-R::
+--recursive::
+   Equivalent of --max-depth=-1 (infinite recursion).
+
 --color[=]::
Color file names. The value must be always (default), never,
or auto.
diff --git a/builtin/ls-files.c b/builtin/ls-files.c
index 1638983..772a6ce 100644
--- a/builtin/ls-files.c
+++ b/builtin/ls-files.c
@@ -725,6 +725,8 @@ int cmd_ls(int argc, const char **argv, const char 
*cmd_prefix)
DIR_SHOW_IGNORED),
OPT_BOOL('u', "unmerged", &show_unmerged,
N_("show unmerged files in the output")),
+   OPT_SET_INT('R', "recursive", &max_depth,
+   N_("shortcut for --max-depth=-1"), -1),
OPT__COLOR(&use_color, N_("show color")),
OPT_COLUMN(0, "column", &colopts, N_("show files in columns")),
{ OPTION_INTEGER, 0, "max-depth", &max_depth, N_("depth"),
-- 
1.9.1.345.ga1a145c

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 15/17] ls: sort output and remove duplicates

2014-03-26 Thread Nguyễn Thái Ngọc Duy
When you mix different file types, with ls-files you may get separate
listing. For example, "ls-files -cm" will show file "abc" twice: one
as part of cached list, one of modified list. With "ls" (and this
patch) they will be in a single sorted list (easier for the eye).

Duplicate entries are also removed. Note that display content is
compared, so if you have "-t" on, or you color file types differently,
you will get duplicate textual entries. This is good imo.

Signed-off-by: Nguyễn Thái Ngọc Duy 
---
 builtin/ls-files.c | 30 +-
 1 file changed, 21 insertions(+), 9 deletions(-)

diff --git a/builtin/ls-files.c b/builtin/ls-files.c
index 392d273..709d8b1 100644
--- a/builtin/ls-files.c
+++ b/builtin/ls-files.c
@@ -57,6 +57,13 @@ static const char *tag_modified = "";
 static const char *tag_skip_worktree = "";
 static const char *tag_resolve_undo = "";
 
+static int compare_output(const void *a_, const void *b_)
+{
+   const struct string_list_item *a = a_;
+   const struct string_list_item *b = b_;
+   return strcmp(a->util, b->util);
+}
+
 static void write_name(struct strbuf *sb, const char *name)
 {
/*
@@ -72,10 +79,12 @@ static void write_name(struct strbuf *sb, const char *name)
quote_path_relative(name, real_prefix, sb);
 }
 
-static void strbuf_fputs(struct strbuf *sb, FILE *fp)
+static void strbuf_fputs(struct strbuf *sb, const char *full_name, FILE *fp)
 {
-   if (column_active(colopts)) {
-   string_list_append(&output, strbuf_detach(sb, NULL));
+   if (column_active(colopts) || porcelain) {
+   struct string_list_item *it;
+   it = string_list_append(&output, strbuf_detach(sb, NULL));
+   it->util = (void*)full_name;
return;
}
fwrite(sb->buf, sb->len, 1, fp);
@@ -110,7 +119,7 @@ static void show_dir_entry(const char *tag, struct 
dir_entry *ent)
strbuf_reset(&sb);
strbuf_addstr(&sb, tag);
write_dir_entry(&sb, ent);
-   strbuf_fputs(&sb, stdout);
+   strbuf_fputs(&sb, ent->name, stdout);
 }
 
 static void show_other_files(struct dir_struct *dir)
@@ -227,7 +236,7 @@ static void show_ce_entry(const char *tag, const struct 
cache_entry *ce)
ce_stage(ce));
}
write_ce_name(&sb, ce);
-   strbuf_fputs(&sb, stdout);
+   strbuf_fputs(&sb, ce->name, stdout);
if (debug_mode) {
const struct stat_data *sd = &ce->ce_stat_data;
 
@@ -535,7 +544,7 @@ static int ls_files(const char **argv, const char *prefix)
if (debug_mode)
die(_("--column and --debug are incompatible"));
}
-   if (column_active(colopts))
+   if (column_active(colopts) || porcelain)
line_terminator = 0;
 
if (require_work_tree && !is_inside_work_tree())
@@ -601,10 +610,13 @@ static int ls_files(const char **argv, const char *prefix)
if (show_resolve_undo)
show_ru_info();
 
-   if (column_active(colopts)) {
-   print_columns(&output, colopts, NULL);
-   string_list_clear(&output, 0);
+   if (porcelain) {
+   qsort(output.items, output.nr, sizeof(*output.items),
+ compare_output);
+   string_list_remove_duplicates(&output, 0);
}
+   print_columns(&output, colopts, NULL);
+   string_list_clear(&output, 0);
 
if (ps_matched) {
int bad;
-- 
1.9.1.345.ga1a145c

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 13/17] ls: add -1 short for --no-column in the spirit of GNU ls

2014-03-26 Thread Nguyễn Thái Ngọc Duy
Signed-off-by: Nguyễn Thái Ngọc Duy 
---
 Documentation/git-ls.txt | 3 +++
 builtin/ls-files.c   | 2 ++
 2 files changed, 5 insertions(+)

diff --git a/Documentation/git-ls.txt b/Documentation/git-ls.txt
index 10df6b0..0480c42 100644
--- a/Documentation/git-ls.txt
+++ b/Documentation/git-ls.txt
@@ -51,6 +51,9 @@ OPTIONS
 --recursive::
Equivalent of --max-depth=-1 (infinite recursion).
 
+-1::
+   Equivalent of --no-column.
+
 --color[=]::
Color file names. The value must be always (default), never,
or auto.
diff --git a/builtin/ls-files.c b/builtin/ls-files.c
index 772a6ce..014de05 100644
--- a/builtin/ls-files.c
+++ b/builtin/ls-files.c
@@ -729,6 +729,8 @@ int cmd_ls(int argc, const char **argv, const char 
*cmd_prefix)
N_("shortcut for --max-depth=-1"), -1),
OPT__COLOR(&use_color, N_("show color")),
OPT_COLUMN(0, "column", &colopts, N_("show files in columns")),
+   OPT_SET_INT('1', NULL, &colopts,
+   N_("shortcut for --no-column"), COL_PARSEOPT),
{ OPTION_INTEGER, 0, "max-depth", &max_depth, N_("depth"),
N_("descend at most  levels"), PARSE_OPT_NONEG,
NULL, 1 },
-- 
1.9.1.345.ga1a145c

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 16/17] ls: do not show duplicate cached entries

2014-03-26 Thread Nguyễn Thái Ngọc Duy
With the current show_files() "ls -tcm" will show

  foo.c
M foo.c

The first item is redundant. If "foo.c" is modified, we know it's in
the cache. Introduce show_files_compact to do that because ls-files is
plumbing and scripts may already depend on current display behavior.

Another difference in show_files_compact() is it does not show
skip-worktree (aka outside sparse checkout) entries anymore, which
makes sense in porcelain context.

Signed-off-by: Nguyễn Thái Ngọc Duy 
---
 builtin/ls-files.c | 52 +++-
 1 file changed, 51 insertions(+), 1 deletion(-)

diff --git a/builtin/ls-files.c b/builtin/ls-files.c
index 709d8b1..cd8e35c 100644
--- a/builtin/ls-files.c
+++ b/builtin/ls-files.c
@@ -337,6 +337,53 @@ static void show_files(struct dir_struct *dir)
}
 }
 
+static void show_files_compact(struct dir_struct *dir)
+{
+   int i;
+
+   /* For cached/deleted files we don't need to even do the readdir */
+   if (show_others || show_killed) {
+   if (!show_others)
+   dir->flags |= DIR_COLLECT_KILLED_ONLY;
+   fill_directory(dir, &pathspec);
+   if (show_others)
+   show_other_files(dir);
+   if (show_killed)
+   show_killed_files(dir);
+   }
+   if (!(show_cached || show_stage || show_deleted || show_modified))
+   return;
+   for (i = 0; i < active_nr; i++) {
+   const struct cache_entry *ce = active_cache[i];
+   struct stat st;
+   int err, shown = 0;
+   if ((dir->flags & DIR_SHOW_IGNORED) &&
+   !ce_excluded(dir, ce))
+   continue;
+   if (show_unmerged && !ce_stage(ce))
+   continue;
+   if (ce->ce_flags & CE_UPDATE)
+   continue;
+   if (ce_skip_worktree(ce))
+   continue;
+   err = lstat(ce->name, &st);
+   if (show_deleted && err) {
+   show_ce_entry(tag_removed, ce);
+   shown = 1;
+   }
+   if (show_modified && ce_modified(ce, &st, 0)) {
+   show_ce_entry(tag_modified, ce);
+   shown = 1;
+   }
+   if (ce_stage(ce)) {
+   show_ce_entry(tag_unmerged, ce);
+   shown = 1;
+   }
+   if (!shown && show_cached)
+   show_ce_entry(tag_cached, ce);
+   }
+}
+
 /*
  * Prune the index to only contain stuff starting with "prefix"
  */
@@ -606,7 +653,10 @@ static int ls_files(const char **argv, const char *prefix)
refresh_index(&the_index, REFRESH_QUIET, &pathspec, NULL, NULL);
setup_pager();
}
-   show_files(&dir);
+   if (porcelain)
+   show_files_compact(&dir);
+   else
+   show_files(&dir);
if (show_resolve_undo)
show_ru_info();
 
-- 
1.9.1.345.ga1a145c

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 17/17] ls: show directories as well as files

2014-03-26 Thread Nguyễn Thái Ngọc Duy
The index does not store directories explicitly (except submodules) so
we have to figure them out from file list. The function
show_directories() deliberately generates duplicate directories and
expects the previous patch to remove duplicates.

Signed-off-by: Nguyễn Thái Ngọc Duy 
---
 builtin/ls-files.c | 41 +
 1 file changed, 41 insertions(+)

diff --git a/builtin/ls-files.c b/builtin/ls-files.c
index cd8e35c..7e50192 100644
--- a/builtin/ls-files.c
+++ b/builtin/ls-files.c
@@ -27,6 +27,7 @@ static int show_resolve_undo;
 static int show_modified;
 static int show_killed;
 static int show_valid_bit;
+static int show_dirs;
 static int line_terminator = '\n';
 static int debug_mode;
 static int use_color;
@@ -337,6 +338,43 @@ static void show_files(struct dir_struct *dir)
}
 }
 
+static void show_directories(const struct cache_entry *ce)
+{
+   static const char *last_directory;
+   struct strbuf sb = STRBUF_INIT;
+   const char *p = ce->name + prefix_len;
+   const char *sep;
+
+   if (last_directory) {
+   int len = strlen(last_directory);
+   if (!strncmp(ce->name, last_directory, len) &&
+   ce->name[len] == '/')
+   p += len + 1;
+   }
+
+   while (*p && (sep = strchr(p, '/'))) {
+   struct strbuf sb2 = STRBUF_INIT;
+   strbuf_reset(&sb);
+   strbuf_add(&sb, ce->name, sep - ce->name);
+   p = sep + 1;
+   if (!match_pathspec(&pathspec, sb.buf, sb.len,
+   prefix_len, NULL, 1))
+   continue;
+   write_name(&sb2, sb.buf);
+   if (want_color(use_color)) {
+   struct strbuf sb3 = STRBUF_INIT;
+   color_filename(&sb3, ce->name, sb2.buf, S_IFDIR, 1);
+   strbuf_release(&sb2);
+   sb2 = sb3;
+   }
+   if (show_tag)
+   strbuf_insert(&sb2, 0, tag_cached, strlen(tag_cached));
+   last_directory = strbuf_detach(&sb, NULL);
+   strbuf_fputs(&sb2, last_directory, NULL);
+   strbuf_release(&sb2);
+   }
+}
+
 static void show_files_compact(struct dir_struct *dir)
 {
int i;
@@ -357,6 +395,8 @@ static void show_files_compact(struct dir_struct *dir)
const struct cache_entry *ce = active_cache[i];
struct stat st;
int err, shown = 0;
+   if (show_dirs)
+   show_directories(ce);
if ((dir->flags & DIR_SHOW_IGNORED) &&
!ce_excluded(dir, ce))
continue;
@@ -825,6 +865,7 @@ int cmd_ls(int argc, const char **argv, const char 
*cmd_prefix)
use_color = -1;
max_depth = 0;
show_tag = -1;
+   show_dirs = 1;
 
argc = parse_options(argc, argv, prefix, builtin_ls_options,
 ls_usage, 0);
-- 
1.9.1.345.ga1a145c

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] builtin/apply.c: use iswspace() to detect line-ending-like chars

2014-03-26 Thread George Papanikolaou
On Tue, Mar 25, 2014 at 6:54 AM, Junio C Hamano  wrote:
> As a tangent, I have a suspicion that the current implementation may
> be wrong at the beginning of the string.  Wouldn't it match " abc"
> and "abc", even though these two strings shouldn't match?

Wouldn't that be accomplished by just removing the leading whitespace check?

I'm somewhat confused about what the function should match. I haven't
grasped it.

--
papanikge's surrogate email.
I may reply back.
http://www.5slingshots.com/
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: Borrowing objects from nearby repositories

2014-03-26 Thread Junio C Hamano
Andrew Keller  writes:

> On Mar 25, 2014, at 6:17 PM, Junio C Hamano  wrote:
> ...
>>> I think that the standard practice with the existing toolset is to
>>> clone with reference and then repack.  That is:
>>> 
>>>$ git clone --reference  git://over/there mine
>>>$ cd mine
>>>$ git repack -a -d
>>> 
>>> And then you can try this:
>>> 
>>>$ mv .git/objects/info/alternates .git/objects/info/alternates.disabled
>>>$ git fsck
>>> 
>>> to make sure that you are no longer borrowing anything from the
>>> borrowee.  Once you are satisfied, you can remove the saved-away
>>> alternates.disabled file.
>> 
>> Oh, I forgot to say that I am not opposed if somebody wants to teach
>> "git clone" a new option to copy its objects from two places,
>> (hopefully) the majority from near-by reference repository and the
>> remainder over the network, without permanently relying on the
>> former via the alternates mechanism.  The implementation of such a
>> feature could even literally be "clone with reference first and then
>> repack" at least initially but even in the final version.

[Administrivia: please wrap your lines to a reasonable length]

> That was actually one of my first ideas - adding some sort of
> '--auto-repack' option to git-clone.  It's a relatively small
> change, and would work.  However, keeping in mind my end goal of
> automating the feature to the point where you could run simply
> 'git clone ', an '--auto-repack' option is more difficult to
> undo.  You would need a new parameter to disable the automatic
> adding of reference repositories, and a new parameter to undo
> '--auto-repack', and you'd have to remember to actually undo both
> of those settings.
>
> In contrast, if the new feature was '--borrow', and the evolution
> of the feature was a global configuration 'fetch.autoBorrow', then
> to turn it off temporarily, one only needs a single new parameter
> '--no-auto-borrow'.  I think this is a cleaner approach than the
> former, although much more work.

I think you may have misread me.  With the "new option", I was
hinting that the "clone --reference && repack && rm alternates"
will be an acceptable internal implementation of the "--borrow"
option that was mentioned in the thread.  I am not sure where you
got the "auto-repack" from.

One of the reasons you may have misread me may be because I made it
sound as if "this may work and when it works you will be happy, but
if it does not work you did not lose very much" by mentioning "mv &&
fsck".  That wasn't what I meant.

The "repack -a" procedure is to make the borrower repository no
longer dependent on the borrowee, and it is supposed to always work.
In fact, this behaviour was the whole reason why "repack" later
learned its "-l" option to disable it, because people who cloned
with "--reference" in order to reduce the disk footprint by sharing
older and more common objects [*1*] were rightfully surprised to see
that the borrowed objects were copied over to their borrower
repository when they ran "repack" [*2*].

Because this is "clone", there is nothing complex to "undo".  Either
it succeeds, or you remove the whole new directory if anything
fails.

I said "even in the final version" for a simple reason: you cannot
cannot do realistically any better than the "clone --reference &&
repack -a d && rm alternates" sequence.

But you would need to know a few things about how Git works in order
to come to that realisation.  Here are some:

 * "clone --borrow" (or whatever we end up calling the option) must
   talk to two repositories:

- We will need to have one upload-pack session with the distant
  origin repository over the network, which will send a complete
  pack.

- We need to also copy objects that weren't sent from the
  distant origin to our repository from the reference one.

 * A single "repack -a -d" (without "-l") after "clone --reference"
   is already a way to do exactly what you need---enumerate what are
   missing in the packfile that was received from the distant origin
   and come up with packfile(s) that contain all and only objects
   the cloned repository needs.

 * You cannot easily concatenate multiple packfiles into a single
   one (or append runs of objects to an existing packfile) to come
   up with a single packfile.

You _could_ shoehorn the logic to "enumerate and read from the
reference, and append them at the end of the packfile received from
the distant origin repository" into the part that talks to the
distant origin repository, but the object layout in the resulting
packfile will be suboptimal [*3*] and the code complexity required
to do so is not worth it [*4*].


[Footnotes]

*1* From the point of view of supporting both camps, i.e. those who
want their borrower repositories to keep sharing the objects
with the borrowee repository and those who want to use a
borrowee repository temporarily while cloning only to reduce the
network cost from the distant upstream, the

Re: [PATCH/RFC 0/6] reuse deltas found by bitmaps

2014-03-26 Thread Junio C Hamano
Jeff King  writes:

>   2. When considering whether a delta can be reused, check the bitmaps
>  to see if the client has the base. If so, allow reuse.
> ...
> The implementation I'm including here is the one I've shown before,
> which does (2). Part of the reason that I'm reposting it before looking
> further into these options is that I've written a t/perf script that can
> help with the analysis.

Conceptually, that feels like a natural extension for the "thin
pack" transfer.  I wouldn't foresee a correctness issue, as long as
the fetcher runs "index-pack --fix-thin" at their end.
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] builtin/apply.c: use iswspace() to detect line-ending-like chars

2014-03-26 Thread Junio C Hamano
George Papanikolaou  writes:

> On Tue, Mar 25, 2014 at 6:54 AM, Junio C Hamano  wrote:
>> As a tangent, I have a suspicion that the current implementation may
>> be wrong at the beginning of the string.  Wouldn't it match " abc"
>> and "abc", even though these two strings shouldn't match?
>
> Wouldn't that be accomplished by just removing the leading whitespace check?

Yes.  I was wondering *what* semantics we want in the first place;
how to implement what I suggested is so trivial that it goes without
saying for the intended audiences of that comment ;-).

> I'm somewhat confused about what the function should match. I haven't
> grasped it.

This function is used when attempting to resurrect a patch that is
whitespace-damaged.  The patch may want to change a line "a_bc" in
the original into something else [*1*], and we may not find "a_bc"
in the current source, but there may be "a__bc" (two spaces instead
of one the whitespace-damaged patch claims to expect).  By ignoring
the amount of whitespaces, it forces "git apply" to consider that
"a_bc" in the broken patch meant to refer to "a__bc" in reality.

I _think_ the original motivation of ignore_ws_change was to match
the "--ignore-space-change" option of "diff", i.e. "ignore changes
in the amount of white space".  I just checked the source
(xdiff/xutils.c) and made sure that "git diff" does not treat the
beginning of line any differently hence "_a_bc" and "a_bc" are not
considered a match under its --ignore-space-change option.

The current implementation of "apply --ignore-space-change" that
ignores leading whitespaces (not "ignore changes in the amount of
leading whitespaces") is likely to be a bug from this point of view.

But I wanted to hear opinions from other Git experts [*2*].  Hence
my "As a tangent, I have a suspicion".


[Footnote]

*1* This mode is not enabled by default.  I am not even sure if
anybody sane would (or should) use this option.  Sure, the fuzzy
match may be able to find the original line that the patch
author may meant to patch even when it is whiltespace-damaged
because it does not fully trust what the original lines exactly
say (i.e. context lines prefixed by " " and old lines prefixed
by "-").  What makes it sane for us to trust what the
replacement lines (i.e. new lines prefixed by "+") in such a
mangled patch says?

*2* For example, somebody may be able to point out that "this is
meant to match the option of the same name 'diff' has", which is
my assumption that leads to the above discussion, may not be
true.
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH/RFC 0/6] reuse deltas found by bitmaps

2014-03-26 Thread Jeff King
On Wed, Mar 26, 2014 at 10:33:41AM -0700, Junio C Hamano wrote:

> Jeff King  writes:
> 
> >   2. When considering whether a delta can be reused, check the bitmaps
> >  to see if the client has the base. If so, allow reuse.
> > ...
> > The implementation I'm including here is the one I've shown before,
> > which does (2). Part of the reason that I'm reposting it before looking
> > further into these options is that I've written a t/perf script that can
> > help with the analysis.
> 
> Conceptually, that feels like a natural extension for the "thin
> pack" transfer.  I wouldn't foresee a correctness issue, as long as
> the fetcher runs "index-pack --fix-thin" at their end.

Right, this is only enabled when --thin is negotiated during the
protocol transfer. I don't think there's any correctness problem here.
But I want to make sure we are doing the fastest thing.

Here's another set of results comparing three runs: v1.9.0 (with no
bitmaps), origin/master (bitmaps), and this series. Apologies for the
long lines.

  Test v1.9.0origin 
HEAD   
  
-
  5311.3: server   (1 days)0.20(0.17+0.02)   0.29(0.34+0.04) +45.0% 
0.14(0.12+0.02) -30.0% 
  5311.4: size (1 days)  56.2K  1.0M +1694.4%   
  59.5K +5.9%  
  5311.5: client   (1 days)0.08(0.07+0.00)   0.03(0.04+0.00) -62.5% 
0.08(0.07+0.00) +0.0%  
  5311.7: server   (2 days)0.06(0.06+0.00)   0.28(0.33+0.04) +366.7%
0.14(0.11+0.02) +133.3%
  5311.8: size (2 days)  56.2K  1.0M +1694.4%   
  59.5K +5.9%  
  5311.9: client   (2 days)0.09(0.08+0.00)   0.03(0.04+0.00) -66.7% 
0.09(0.08+0.00) +0.0%  
  5311.11: server   (4 days)   0.21(0.18+0.02)   0.29(0.33+0.03) +38.1% 
0.14(0.11+0.02) -33.3% 
  5311.12: size (4 days) 64.2K  1.1M +1536.6%   
  67.9K +5.8%  
  5311.13: client   (4 days)   0.08(0.08+0.00)   0.04(0.03+0.01) -50.0% 
0.09(0.07+0.01) +12.5% 
  5311.15: server   (8 days)   0.22(0.21+0.02)   0.36(0.47+0.03) +63.6% 
0.14(0.11+0.02) -36.4% 
  5311.16: size (8 days)125.7K  1.5M +1100.8%   
 130.1K +3.5%  
  5311.17: client   (8 days)   0.11(0.10+0.00)   0.05(0.05+0.00) -54.5% 
0.13(0.11+0.01) +18.2% 
  5311.19: server  (16 days)   0.26(0.26+0.03)   0.76(1.20+0.04) +192.3%
0.25(0.21+0.04) -3.8%  
  5311.20: size(16 days)358.6K  3.7M +931.7%
 359.8K +0.3%  
  5311.21: client  (16 days)   0.28(0.27+0.01)   0.13(0.15+0.00) -53.6% 
0.30(0.28+0.02) +7.1%  
  5311.23: server  (32 days)   0.44(0.54+0.07)   1.39(2.54+0.04) +215.9%
0.28(0.23+0.04) -36.4% 
  5311.24: size(32 days)  1.1M  8.6M +652.4%
   2.1M +83.9% 
  5311.25: client  (32 days)   0.66(0.64+0.02)   0.32(0.38+0.01) -51.5% 
0.69(0.67+0.04) +4.5%  
  5311.27: server  (64 days)   2.78(4.02+0.17)   7.02(15.59+0.16) +152.5%   
0.43(0.37+0.07) -84.5% 
  5311.28: size(64 days) 18.7M 68.3M +265.5%
  24.5M +31.3% 
  5311.29: client  (64 days)   6.25(6.29+0.16)   3.21(4.76+0.14) -48.6% 
6.27(6.46+0.18) +0.3%  
  5311.31: server (128 days)   4.48(7.32+0.21)   7.56(16.60+0.16) +68.8%
0.51(0.45+0.10) -88.6% 
  5311.32: size   (128 days) 25.8M 83.1M +222.3%
  35.9M +39.2% 
  5311.33: client (128 days)   7.32(7.58+0.17)   3.94(5.87+0.18) -46.2% 
7.15(7.80+0.20) -2.3%  

My previous results showed that this series was an improvement over
straight bitmaps. But what it didn't show is that bitmaps actually
provide a regression for some fetches (I think because we do not find
the boundary commits at all, and do not have any preferred bases).

Just looking at the 128-day case again, using bitmaps increased our
server CPU time _and_ made a much bigger pack. This series not only
fixes the CPU time regression, but it also drops the server CPU time to
almost nothing. That's a nice improvement, and it makes perfect sense:
we are reusing on-disk deltas instead of on-the-fly computing deltas
against the preferred bases.

And it does help with the size regression, though the end result is
still a bit worse than v1.9.0. I'm not exactly sure what's going on
here. My guess is that we have objects to send that are not deltas on
disk (probably because they are at the tip of history and other things
are deltas against them). We would still want to do delta compression of
them against preferred bases, but we don't have any preferred bases in
our list.

So I think we still want to add back in some list of preferred base
objects when bitmaps are in use. The question is, which objects?
With bitmaps, it's easy to add in all of the objects the client has, but
that is probably going to be counterproductive (I sti

Re: [PATCH 5/5] log: do not segfault on gmtime errors

2014-03-26 Thread Jeff King
On Wed, Mar 26, 2014 at 11:05:59AM +, Charles Bailey wrote:

> On Mon, Feb 24, 2014 at 02:49:05AM -0500, Jeff King wrote:
> > +# date is within 2^63-1, but enough to choke glibc's gmtime
> > +test_expect_success 'absurdly far-in-future dates produce sentinel' '
> > +   commit=$(munge_author_date HEAD 99) &&
> > +   echo "Thu Jan 1 00:00:00 1970 +" >expect &&
> > +   git log -1 --format=%ad $commit >actual &&
> > +   test_cmp expect actual
> > +'
> 
> Git on AIX seems happy to convert this to Thu Oct 24 18:46:39
> 162396404 -0700. I don't know if this is correct for the given input
> but the test fails.

Ick. I am not sure that dates at that range are even meaningful (will
October really exist in the year 162396404? Did they account for all the
leap-seconds between then and now?). But at the same time, I cannot
fault their gmtime for just extrapolating the current rules out as far
as we ask them to.

Unlike the FreeBSD thing that René brought up, this is not a problem in
the code, but just in the test. So I think our options are basically:

  1. Scrap the test as unportable.

  2. Hard-code a few expected values. I'd be unsurprised if some other
 system comes up with a slightly different date in 162396404, so we
 may end up needing several of these.

I think I'd lean towards (2), just because it is testing an actual
feature of the code, and I'd like to continue doing so. And while we may
end up with a handful of values, there's probably not _that_ many
independent implementations of gmtime in the wild.

-Peff
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 12/19] tree-diff: remove special-case diff-emitting code for empty-tree cases

2014-03-26 Thread Kirill Smelkov
On Tue, Mar 25, 2014 at 10:45:01AM -0700, Junio C Hamano wrote:
> Kirill Smelkov  writes:
> 
> >> >  static int tree_entry_pathcmp(struct tree_desc *t1, struct tree_desc 
> >> > *t2)
> >> >  {
> >> >  struct name_entry *e1, *e2;
> >> >  int cmp;
> >> >  
> >> > +if (!t1->size)
> >> > +return t2->size ? +1 /* +∞ > c */  : 0 /* +∞ = +∞ */;
> >> > +else if (!t2->size)
> >> > +return -1;  /* c < +∞ */
> >> 
> >> Where do these "c" come from?  I somehow feel that these comments
> >> are making it harder to understand what is going on.
> >
> > "c" means some finite "c"onstant here. When I was studying at school and
> > at the university, it was common to denote constants via this letter -
> > i.e. in algebra and operators they often show scalar multiplication as
> >
> > c·A (or α·A)
> >
> > etc. I understand it could maybe be confusing (but it came to me as
> > surprise), so would the following be maybe better:
> >
> > if (!t1->size)
> > return t2->size ? +1 /* +∞ > const */  : 0 /* +∞ = +∞ */;
> > else if (!t2->size)
> > return -1;  /* const < +∞ */
> >
> > ?
> 
> Not better at all, I am afraid.  A "const" in the code usually means
> "something that does not change, as opposed to a variable", but what
> you are saying here is "t1 does not have an element but t2 still
> does. Pretend as if t1 has a virtual/fake element that is larger
> than any real element t2 may happen to have at the head of its
> queue", and you are labeling that "real element at the head of t2"
> as "const", but as the walker advances, the head element in t1 and
> t2 will change---they are not "const" in that sense, and the reader
> is left scratching his head seeing "const" there, wondering what the
> author of the comment meant.

I agree.


> "real" or "concrete" might be better a phrasing, but I do not think
> having "/* +inf > concrete */" there helps the reader understand
> what is going on in the first place.  Perhaps:
> 
> /*
>  * When one side is empty, pretend that it has an element
>  * that sorts later than what the other non-empty side has,
>  * so that the caller advances the non-empty side without
>  * touching the empty side.
>  */
> if (!t1->size)
> return !t2->size ? 0 : 1;
> else if (!t2->size)
> return -1;
> 
> or something?

Yes, that describe the reasoning without stranger symbols. How about
taking it further with

  * NOTE empty (=invalid) descriptor(s) take part in comparison as 
+infty,
  *  so that they sort *after* valid tree entries.
  *
  *  Due to this convention, if trees are scanned in sorted order, 
all
  *  non-empty descriptors will be processed first.
  */
 static int tree_entry_pathcmp(struct tree_desc *t1, struct tree_desc 
*t2)
 {
struct name_entry *e1, *e2;
int cmp;
 
/* empty descriptors sort after valid tree entries */
if (!t1->size)
return t2->size ? +1 : 0;
else if (!t2->size)
return -1;

?

On Tue, Mar 25, 2014 at 03:07:33PM -0700, Junio C Hamano wrote:
> Kirill Smelkov  writes:
> 
> > On Mon, Mar 24, 2014 at 02:18:10PM -0700, Junio C Hamano wrote:
> >> Kirill Smelkov  writes:
> >> 
> >> > via teaching tree_entry_pathcmp() how to compare empty tree descriptors:
> >> 
> >> Drop this line, as you explain the "pretend empty compares bigger
> >> than anything else" idea later anyway?  This early part of the
> >> proposed log message made me hiccup while reading it.
> >
> > Hmm, I was trying to show the big picture first and only then details...
> 
> The subject should be sufficient for the big picture.  "OK, we are
> removing the special casing" is what we expect the reader to get.
> Then, this
> 
> >> > While walking trees, we iterate their entries from lowest to highest in
> >> > sort order, so empty tree means all entries were already went over.
> 
> sets the background.  "OK, the code walks two trees, both have
> sorted elements, in parallel." is what we want the reader to
> understand.  Then the next part gives the idea of pretending that
> the empty-side always compare later than the non-empty side while
> doing that parallel walking (similar to "merge").
> 
> So, yes, I think it is a good presentation order to give big picture
> punch-line first on the subject, some background and then the
> solution.

Ok, let it be this way and let's drop it.

Here is updated patch:
(please keep author email)

 8< 
From: Kirill Smelkov 
Date: Mon, 24 Feb 2014 20:21:44 +0400
Subject: [PATCH v2] tree-diff: remove special-case diff-emitting code for 
empty-tree cases

While walking trees, we iterate their entries from lowest to highest in
sort order, so empty tree means all entries were

Re: [PATCH v2 14/27] update-ref.c: Extract a new function, parse_next_sha1()

2014-03-26 Thread Brad King
On 03/24/2014 01:56 PM, Michael Haggerty wrote:
> +/*
> + * For backwards compatibility, accept an empty string for create's
> + *  in binary mode to be equivalent to specifying zeros.
> + */
> +#define PARSE_SHA1_ALLOW_EMPTY 0x02

The comment should say "update's", not "create's".

-Brad

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v2 16/27] t1400: Test one mistake at a time

2014-03-26 Thread Brad King
On 03/24/2014 01:56 PM, Michael Haggerty wrote:
> Signed-off-by: Michael Haggerty 
> 
> t1400: Add a test of "update" with too few arguments
> 
> Signed-off-by: Michael Haggerty 

This looks like a stray squash message.

-Brad

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v2 00/27] Clean up update-refs --stdin and implement ref_transaction

2014-03-26 Thread Brad King
On 03/24/2014 01:56 PM, Michael Haggerty wrote:
> Changes relative to v1:
> 
> * Rename the functions associated with ref_transactions to be more
>   reminiscent of database transactions:
> 
>   * create_ref_transaction() -> ref_transaction_begin()
>   * free_ref_transaction() -> ref_transaction_rollback()
>   * queue_update_ref() -> ref_transaction_update()
>   * queue_create_ref() -> ref_transaction_create()
>   * queue_delete_ref() -> ref_transaction_delete()
>   * commit_ref_transaction() -> ref_transaction_commit()

Those new names look better.

> * Fix backwards compatibility of "git update-ref --stdin -z"'s
>   handling of the "create" command: allow  to be the empty
>   string, treating it the same zeros.  But deprecate this usage.

The changes related to that look good.  The new documentation is
much clearer than my old wording.

Series v2 looks good to me except for my responses to individual
commits.

Thanks,
-Brad

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v2 19/27] refs: Add a concept of a reference transaction

2014-03-26 Thread Brad King
On 03/24/2014 01:56 PM, Michael Haggerty wrote:
> +void ref_transaction_update(struct ref_transaction *transaction,
> + const char *refname,
> + unsigned char *new_sha1, unsigned char *old_sha1,
> + int flags, int have_old);
[snip]
> +void ref_transaction_create(struct ref_transaction *transaction,
> + const char *refname,
> + unsigned char *new_sha1,
> + int flags);
[snip]
> +void ref_transaction_delete(struct ref_transaction *transaction,
> + const char *refname,
> + unsigned char *old_sha1,
> + int flags, int have_old);

Perhaps we also need:

void ref_transaction_verify(struct ref_transaction *transaction,
const char *refname,
unsigned char *old_sha1,
int flags, int have_old);

as equivalent to the "verify" command in "update-ref --stdin"?

-Brad

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH] t4212: handle systems with post-apocalyptic gmtime

2014-03-26 Thread Jeff King
One of the tests in t4212 checks our behavior when we feed
gmtime a date so far in the future that it gives up and
returns NULL.

But some gmtime implementations just refuse to quit. They
soldier on, giving us a glimpse of a chilly October evening
some 160 million years in the future (and presumably filled
with our leather-clad horseback-riding ape descendants).

Let's allow the test to match either the sentinel value
(i.e., what we want when gmtime gives up) or any reasonable
value returned by known implementations.

Reported-by: Charles Bailey 
Signed-off-by: Jeff King 
---
On top of jk/commit-dates-parsing-fix (though the test is already in
v1.9.1).

 t/t4212-log-corrupt.sh | 23 +++
 1 file changed, 19 insertions(+), 4 deletions(-)

diff --git a/t/t4212-log-corrupt.sh b/t/t4212-log-corrupt.sh
index 85c6df4..08f982c 100755
--- a/t/t4212-log-corrupt.sh
+++ b/t/t4212-log-corrupt.sh
@@ -76,12 +76,27 @@ test_expect_success 'date parser recognizes time_t 
overflow' '
test_cmp expect actual
 '
 
-# date is within 2^63-1, but enough to choke glibc's gmtime
-test_expect_success 'absurdly far-in-future dates produce sentinel' '
+cmp_one_of () {
+   for candidate in "$@"; do
+   echo "$candidate" >expect &&
+   test_cmp expect actual &&
+   return 0
+   done
+   return 1
+}
+
+# date is within 2^63-1, but enough to choke glibc's gmtime.
+# We check that either the date broke gmtime (and we return the
+# usual epoch value), or gmtime gave us some sensible value.
+#
+# The sensible values are determined experimentally. The first
+# is from AIX.
+test_expect_success 'absurdly far-in-future dates' '
commit=$(munge_author_date HEAD 99) &&
-   echo "Thu Jan 1 00:00:00 1970 +" >expect &&
git log -1 --format=%ad $commit >actual &&
-   test_cmp expect actual
+   cmp_one_of \
+   "Thu Jan 1 00:00:00 1970 +" \
+   "Thu Oct 24 18:46:39 162396404 -0700"
 '
 
 test_done
-- 
1.9.1.656.ge8a0637

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 5/5] log: do not segfault on gmtime errors

2014-03-26 Thread Junio C Hamano
Jeff King  writes:

> On Wed, Mar 26, 2014 at 11:05:59AM +, Charles Bailey wrote:
>
>> On Mon, Feb 24, 2014 at 02:49:05AM -0500, Jeff King wrote:
>> > +# date is within 2^63-1, but enough to choke glibc's gmtime
>> > +test_expect_success 'absurdly far-in-future dates produce sentinel' '
>> > +  commit=$(munge_author_date HEAD 99) &&
>> > +  echo "Thu Jan 1 00:00:00 1970 +" >expect &&
>> > +  git log -1 --format=%ad $commit >actual &&
>> > +  test_cmp expect actual
>> > +'
>> 
>> Git on AIX seems happy to convert this to Thu Oct 24 18:46:39
>> 162396404 -0700. I don't know if this is correct for the given input
>> but the test fails.
>
> Ick. I am not sure that dates at that range are even meaningful (will
> October really exist in the year 162396404? Did they account for all the
> leap-seconds between then and now?). But at the same time, I cannot
> fault their gmtime for just extrapolating the current rules out as far
> as we ask them to.
>
> Unlike the FreeBSD thing that René brought up, this is not a problem in
> the code, but just in the test. So I think our options are basically:
>
>   1. Scrap the test as unportable.
>
>   2. Hard-code a few expected values. I'd be unsurprised if some other
>  system comes up with a slightly different date in 162396404, so we
>  may end up needing several of these.
>
> I think I'd lean towards (2), just because it is testing an actual
> feature of the code, and I'd like to continue doing so. And while we may
> end up with a handful of values, there's probably not _that_ many
> independent implementations of gmtime in the wild.

Or "3. Just make sure that 'git log' does not segfault"?
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 5/5] log: do not segfault on gmtime errors

2014-03-26 Thread Jeff King
On Wed, Mar 26, 2014 at 11:58:49AM -0700, Junio C Hamano wrote:

> > Unlike the FreeBSD thing that René brought up, this is not a problem in
> > the code, but just in the test. So I think our options are basically:
> >
> >   1. Scrap the test as unportable.
> >
> >   2. Hard-code a few expected values. I'd be unsurprised if some other
> >  system comes up with a slightly different date in 162396404, so we
> >  may end up needing several of these.
> >
> > I think I'd lean towards (2), just because it is testing an actual
> > feature of the code, and I'd like to continue doing so. And while we may
> > end up with a handful of values, there's probably not _that_ many
> > independent implementations of gmtime in the wild.
> 
> Or "3. Just make sure that 'git log' does not segfault"?

That would not test the FreeBSD case, which does not segfault, but
returns a bogus sentinel value.

I don't know how important that is. This is such a minor feature that it
is not worth a lot of maintenance headache in the test. But I also do
not know if this is going to be the last report, or we will have a bunch
of other systems that need their own special values put into the test.

-Peff
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v2 06/17] ls-files: add --color to highlight file names

2014-03-26 Thread Eric Sunshine
On Wed, Mar 26, 2014 at 9:48 AM, Nguyễn Thái Ngọc Duy  wrote:
> Signed-off-by: Nguyễn Thái Ngọc Duy 
> ---
>  Documentation/git-ls-files.txt |  9 +
>  builtin/ls-files.c | 38 +++---
>  2 files changed, 44 insertions(+), 3 deletions(-)
>
> diff --git a/Documentation/git-ls-files.txt b/Documentation/git-ls-files.txt
> index c0856a6..5c1b7f3 100644
> --- a/Documentation/git-ls-files.txt
> +++ b/Documentation/git-ls-files.txt
> @@ -147,6 +147,15 @@ a space) at the start of each line:
> possible for manual inspection; the exact format may change at
> any time.
>
> +--color[=]::
> +   Color file names. The value must be always (default), never,
> +   or auto.

Here, the default is "always"...

> +--no-color::
> +   Turn off coloring, even when the configuration file gives the
> +   default to color output, same as `--color=never`. This is the
> +   default.

But, here the default is "never".

> +
>  \--::
> Do not interpret any more arguments as options.
>
> diff --git a/builtin/ls-files.c b/builtin/ls-files.c
> index 6e30592..2857b38 100644
> --- a/builtin/ls-files.c
> +++ b/builtin/ls-files.c
> @@ -14,6 +14,7 @@
>  #include "resolve-undo.h"
>  #include "string-list.h"
>  #include "pathspec.h"
> +#include "color.h"
>
>  static int abbrev;
>  static int show_deleted;
> @@ -27,6 +28,7 @@ static int show_killed;
>  static int show_valid_bit;
>  static int line_terminator = '\n';
>  static int debug_mode;
> +static int use_color;
>
>  static const char *prefix;
>  static int max_prefix_len;
> @@ -60,7 +62,6 @@ static void write_name(struct strbuf *sb, const char *name)
> strbuf_release(&sb2);
> } else
> quote_path_relative(name, real_prefix, sb);
> -   strbuf_addch(sb, line_terminator);
>  }
>
>  static void strbuf_fputs(struct strbuf *sb, FILE *fp)
> @@ -68,6 +69,21 @@ static void strbuf_fputs(struct strbuf *sb, FILE *fp)
> fwrite(sb->buf, sb->len, 1, fp);
>  }
>
> +static void write_dir_entry(struct strbuf *sb, const struct dir_entry *ent)
> +{
> +   struct strbuf quoted = STRBUF_INIT;
> +   struct stat st;
> +   if (stat(ent->name, &st))
> +   st.st_mode = 0;
> +   write_name("ed, ent->name);
> +   if (want_color(use_color))
> +   color_filename(sb, ent->name, quoted.buf, st.st_mode, 1);
> +   else
> +   strbuf_addbuf(sb, "ed);
> +   strbuf_addch(sb, line_terminator);
> +   strbuf_release("ed);
> +}
> +
>  static void show_dir_entry(const char *tag, struct dir_entry *ent)
>  {
> static struct strbuf sb = STRBUF_INIT;
> @@ -81,7 +97,7 @@ static void show_dir_entry(const char *tag, struct 
> dir_entry *ent)
>
> strbuf_reset(&sb);
> strbuf_addstr(&sb, tag);
> -   write_name(&sb, ent->name);
> +   write_dir_entry(&sb, ent);
> strbuf_fputs(&sb, stdout);
>  }
>
> @@ -146,6 +162,18 @@ static void show_killed_files(struct dir_struct *dir)
> }
>  }
>
> +static void write_ce_name(struct strbuf *sb, const struct cache_entry *ce)
> +{
> +   struct strbuf quoted = STRBUF_INIT;
> +   write_name("ed, ce->name);
> +   if (want_color(use_color))
> +   color_filename(sb, ce->name, quoted.buf, ce->ce_mode, 1);
> +   else
> +   strbuf_addbuf(sb, "ed);
> +   strbuf_addch(sb, line_terminator);
> +   strbuf_release("ed);
> +}
> +
>  static void show_ce_entry(const char *tag, const struct cache_entry *ce)
>  {
> static struct strbuf sb = STRBUF_INIT;
> @@ -186,7 +214,7 @@ static void show_ce_entry(const char *tag, const struct 
> cache_entry *ce)
> find_unique_abbrev(ce->sha1,abbrev),
> ce_stage(ce));
> }
> -   write_name(&sb, ce->name);
> +   write_ce_name(&sb, ce);
> strbuf_fputs(&sb, stdout);
> if (debug_mode) {
> const struct stat_data *sd = &ce->ce_stat_data;
> @@ -523,6 +551,7 @@ int cmd_ls_files(int argc, const char **argv, const char 
> *cmd_prefix)
> N_("if any  is not in the index, treat this as 
> an error")),
> OPT_STRING(0, "with-tree", &with_tree, N_("tree-ish"),
> N_("pretend that paths removed since  are 
> still present")),
> +   OPT__COLOR(&use_color, N_("show color")),
> OPT__ABBREV(&abbrev),
> OPT_BOOL(0, "debug", &debug_mode, N_("show debugging data")),
> OPT_END()
> @@ -570,6 +599,9 @@ int cmd_ls_files(int argc, const char **argv, const char 
> *cmd_prefix)
> if (require_work_tree && !is_inside_work_tree())
> setup_work_tree();
>
> +   if (want_color(use_color))
> +   parse_ls_color();
> +
> parse_pathspec(&pathspec, 0,
>PATHSPEC_PREFER_CWD |
>PATHSPEC_STRIP_SUBMODULE_SLASH_CHEAP,
>

Re: [PATCH v2 03/17] ls_colors.c: add function to color a file name

2014-03-26 Thread Eric Sunshine
On Wed, Mar 26, 2014 at 9:48 AM, Nguyễn Thái Ngọc Duy  wrote:
> Tthe new function is based on print_color_indicator() from commit

s/Tthe/The/

> 7326d1f1a67edf21947ae98194f98c38b6e9e527 in coreutils.git.
>
> Signed-off-by: Nguyễn Thái Ngọc Duy 
> ---
>  color.h |  2 ++
>  ls_colors.c | 66 
> +
>  2 files changed, 68 insertions(+)
>
> diff --git a/color.h b/color.h
> index 640fc48..398369a 100644
> --- a/color.h
> +++ b/color.h
> @@ -94,5 +94,7 @@ void color_print_strbuf(FILE *fp, const char *color, const 
> struct strbuf *sb);
>  int color_is_nil(const char *color);
>
>  void parse_ls_color(void);
> +void color_filename(struct strbuf *sb, const char *name,
> +   const char *display_name, mode_t mode, int linkok);
>
>  #endif /* COLOR_H */
> diff --git a/ls_colors.c b/ls_colors.c
> index cef5a92..1125329 100644
> --- a/ls_colors.c
> +++ b/ls_colors.c
> @@ -422,3 +422,69 @@ void parse_ls_color(void)
> color_symlink_as_referent = 1;
> git_config(ls_colors_config, NULL);
>  }
> +
> +void color_filename(struct strbuf *sb, const char *name,
> +   const char *display_name, mode_t mode, int linkok)
> +{
> +   int type;
> +   struct color_ext_type *ext; /* Color extension */
> +
> +   if (S_ISREG (mode)) {
> +   type = LS_FL;
> +   if ((mode & S_ISUID) != 0)
> +   type = LS_SU;
> +   else if ((mode & S_ISGID) != 0)
> +   type = LS_SG;
> +   else if ((mode & (S_IXUSR | S_IXGRP | S_IXOTH)) != 0)
> +   type = LS_EX;
> +   } else if (S_ISDIR (mode)) {
> +   if ((mode & S_ISVTX) && (mode & S_IWOTH))
> +   type = LS_TW;
> +   else if ((mode & S_IWOTH) != 0)
> +   type = LS_OW;
> +   else if ((mode & S_ISVTX) != 0)
> +   type = LS_ST;
> +   else
> +   type = LS_DI;
> +   } else if (S_ISLNK (mode))
> +   type = (!linkok && *ls_colors[LS_OR]) ? LS_OR : LS_LN;
> +   else if (S_ISFIFO (mode))
> +   type = LS_PI;
> +   else if (S_ISSOCK (mode))
> +   type = LS_SO;
> +   else if (S_ISBLK (mode))
> +   type = LS_BD;
> +   else if (S_ISCHR (mode))
> +   type = LS_CD;
> +#ifdef S_ISDOOR
> +   else if (S_ISDOOR (mode))
> +   type = LS_DO;
> +#endif
> +   else
> +   /* Classify a file of some other type as C_ORPHAN.  */
> +   type = LS_OR;
> +
> +   /* Check the file's suffix only if still classified as C_FILE.  */
> +   ext = NULL;
> +   if (type == LS_FL) {
> +   /* Test if NAME has a recognized suffix.  */
> +   size_t len = strlen(name);
> +   const char *p = name + len; /* Pointer to final 
> \0.  */
> +   for (ext = color_ext_list; ext != NULL; ext = ext->next) {
> +   if (ext->ext.len <= len &&
> +   !strncmp(p - ext->ext.len, ext->ext.string, 
> ext->ext.len))
> +   break;
> +   }
> +   }
> +
> +   if (display_name)
> +   name = display_name;
> +   if (ext)
> +   strbuf_addf(sb, "\033[%.*sm%s%s",
> +   (int)ext->seq.len, ext->seq.string,
> +   name, GIT_COLOR_RESET);
> +   else if (*ls_colors[type])
> +   strbuf_addf(sb, "%s%s%s", ls_colors[type], name, 
> GIT_COLOR_RESET);
> +   else
> +   strbuf_addstr(sb, name);
> +}
> --
> 1.9.1.345.ga1a145c
>
> --
> To unsubscribe from this list: send the line "unsubscribe git" in
> the body of a message to majord...@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] t4212: handle systems with post-apocalyptic gmtime

2014-03-26 Thread Junio C Hamano
Jeff King  writes:

> +cmp_one_of () {
> + for candidate in "$@"; do

Style ;-)

> + echo "$candidate" >expect &&
> + test_cmp expect actual &&
> + return 0
> + done
> + return 1
> +}

It actually may be easier to understand if you write a trivial case
statement at the sole calling site of this helper function, though.

In any case, would it really be essential to make sure that the
output shows a phony (or a seemingly real) datestamp for this test?

The primary thing you wanted to achieve by the "gmtime gave us NULL,
let's substitute it with an arbitrary value to avoid dereferencing
the NULL" change was *not* that we see that same arbitrary value
comes out of the system, but that we do not die by attempting to
reference the NULL, I think.  Not dying is the primary thing we want
to (and we already do) test, no?

> +# date is within 2^63-1, but enough to choke glibc's gmtime.
> +# We check that either the date broke gmtime (and we return the
> +# usual epoch value), or gmtime gave us some sensible value.
> +#
> +# The sensible values are determined experimentally. The first
> +# is from AIX.
> +test_expect_success 'absurdly far-in-future dates' '
>   commit=$(munge_author_date HEAD 99) &&
> - echo "Thu Jan 1 00:00:00 1970 +" >expect &&
>   git log -1 --format=%ad $commit >actual &&
> - test_cmp expect actual
> + cmp_one_of \
> + "Thu Jan 1 00:00:00 1970 +" \
> + "Thu Oct 24 18:46:39 162396404 -0700"
>  '
>  
>  test_done
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v2 05/17] ls-files: buffer full item in strbuf before printing

2014-03-26 Thread Eric Sunshine
On Wed, Mar 26, 2014 at 9:48 AM, Nguyễn Thái Ngọc Duy  wrote:
> Buffering so that we can manipulate the strings (e.g. coloring)
> further before finally printing them.
>
> Signed-off-by: Nguyễn Thái Ngọc Duy 
> ---
>  builtin/ls-files.c | 48 +++-
>  1 file changed, 35 insertions(+), 13 deletions(-)
>
> diff --git a/builtin/ls-files.c b/builtin/ls-files.c
> index 47c3880..6e30592 100644
> --- a/builtin/ls-files.c
> +++ b/builtin/ls-files.c
> @@ -47,18 +47,30 @@ static const char *tag_modified = "";
>  static const char *tag_skip_worktree = "";
>  static const char *tag_resolve_undo = "";
>
> -static void write_name(const char *name)
> +static void write_name(struct strbuf *sb, const char *name)
>  {
> /*
>  * With "--full-name", prefix_len=0; this caller needs to pass
>  * an empty string in that case (a NULL is good for "").
>  */
> -   write_name_quoted_relative(name, prefix_len ? prefix : NULL,
> -  stdout, line_terminator);
> +   const char *real_prefix = prefix_len ? prefix : NULL;
> +   if (!line_terminator) {
> +   struct strbuf sb2 = STRBUF_INIT;
> +   strbuf_addstr(sb, relative_path(name, real_prefix, &sb2));
> +   strbuf_release(&sb2);
> +   } else
> +   quote_path_relative(name, real_prefix, sb);
> +   strbuf_addch(sb, line_terminator);
> +}
> +
> +static void strbuf_fputs(struct strbuf *sb, FILE *fp)
> +{
> +   fwrite(sb->buf, sb->len, 1, fp);
>  }
>
>  static void show_dir_entry(const char *tag, struct dir_entry *ent)
>  {
> +   static struct strbuf sb = STRBUF_INIT;
> int len = max_prefix_len;
>
> if (len >= ent->len)
> @@ -67,8 +79,10 @@ static void show_dir_entry(const char *tag, struct 
> dir_entry *ent)
> if (!dir_path_match(ent, &pathspec, len, ps_matched))
> return;
>
> -   fputs(tag, stdout);
> -   write_name(ent->name);
> +   strbuf_reset(&sb);
> +   strbuf_addstr(&sb, tag);
> +   write_name(&sb, ent->name);
> +   strbuf_fputs(&sb, stdout);

strbuf_release(&sb);

>  }
>
>  static void show_other_files(struct dir_struct *dir)
> @@ -134,6 +148,7 @@ static void show_killed_files(struct dir_struct *dir)
>
>  static void show_ce_entry(const char *tag, const struct cache_entry *ce)
>  {
> +   static struct strbuf sb = STRBUF_INIT;
> int len = max_prefix_len;
>
> if (len >= ce_namelen(ce))
> @@ -161,16 +176,18 @@ static void show_ce_entry(const char *tag, const struct 
> cache_entry *ce)
> tag = alttag;
> }
>
> +   strbuf_reset(&sb);

'sb' is empty at this point. Why reset it?

> if (!show_stage) {
> -   fputs(tag, stdout);
> +   strbuf_addstr(&sb, tag);
> } else {
> -   printf("%s%06o %s %d\t",
> -  tag,
> -  ce->ce_mode,
> -  find_unique_abbrev(ce->sha1,abbrev),
> -  ce_stage(ce));
> +   strbuf_addf(&sb, "%s%06o %s %d\t",
> +   tag,
> +   ce->ce_mode,
> +   find_unique_abbrev(ce->sha1,abbrev),
> +   ce_stage(ce));
> }
> -   write_name(ce->name);
> +   write_name(&sb, ce->name);
> +   strbuf_fputs(&sb, stdout);

strbuf_release(&sb);

> if (debug_mode) {
> const struct stat_data *sd = &ce->ce_stat_data;
>
> @@ -206,7 +223,12 @@ static void show_ru_info(void)
> printf("%s%06o %s %d\t", tag_resolve_undo, 
> ui->mode[i],
>find_unique_abbrev(ui->sha1[i], abbrev),
>i + 1);
> -   write_name(path);
> +   /*
> +* With "--full-name", prefix_len=0; this caller 
> needs to pass
> +* an empty string in that case (a NULL is good for 
> "").
> +*/
> +   write_name_quoted_relative(path, prefix_len ? prefix 
> : NULL,
> +  stdout, line_terminator);
> }
> }
>  }
> --
> 1.9.1.345.ga1a145c
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [RFC/PATCH 1/4] test-lib: add test_dir_is_empty()

2014-03-26 Thread Jens Lehmann
Am 26.03.2014 11:43, schrieb Michael Haggerty:
> On 03/26/2014 09:29 AM, Jens Lehmann wrote:
>> Am 25.03.2014 21:49, schrieb Junio C Hamano:
>>> Jens Lehmann  writes:
  t/test-lib-functions.sh | 11 +++
  1 file changed, 11 insertions(+)

 diff --git a/t/test-lib-functions.sh b/t/test-lib-functions.sh
 index 158e10a..93d10cd 100644
 --- a/t/test-lib-functions.sh
 +++ b/t/test-lib-functions.sh
 @@ -489,6 +489,17 @@ test_path_is_dir () {
fi
  }

 +# Check if the directory exists and is empty as expected, barf otherwise.
 +test_dir_is_empty () {
 +  test_path_is_dir "$1" &&
 +  if test $(ls -a1 "$1" | wc -l) != 2
 +  then
 +  echo "Directory '$1' is not empty, it contains:"
 +  ls -la "$1"
 +  return 1
 +  fi
 +}
 +
  test_path_is_missing () {
if [ -e "$1" ]
then
> 
> Why not do something like
> 
> test -z "$(ls -a1 "$1" | egrep -v '^\.\.?$')"
> 
> I.e., make the test ignore "." and ".." without depending on their
> existence?

Thanks, will do so in the next round.
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] t4212: handle systems with post-apocalyptic gmtime

2014-03-26 Thread Jeff King
On Wed, Mar 26, 2014 at 12:18:25PM -0700, Junio C Hamano wrote:

> > +   echo "$candidate" >expect &&
> > +   test_cmp expect actual &&
> > +   return 0
> > +   done
> > +   return 1
> > +}
> 
> It actually may be easier to understand if you write a trivial case
> statement at the sole calling site of this helper function, though.

Yeah, perhaps. I wanted to build on test_cmp because it has nice output
for the failure case, but it is probably simple enough to do:

  output=$(cat actual)
  case "$output" in
  ...
  *) echo >&2 "unrecognized date: $output"

> In any case, would it really be essential to make sure that the
> output shows a phony (or a seemingly real) datestamp for this test?
> 
> The primary thing you wanted to achieve by the "gmtime gave us NULL,
> let's substitute it with an arbitrary value to avoid dereferencing
> the NULL" change was *not* that we see that same arbitrary value
> comes out of the system, but that we do not die by attempting to
> reference the NULL, I think.  Not dying is the primary thing we want
> to (and we already do) test, no?

I think there are really two separate behaviors we are testing here (and
in the surrounding tests):

  1. Don't segfault if gmtime returns NULL.

  2. Whenever we cannot process a date (either because gmtime fails, or
 because we fail before even getting the value to gmtime),
 consistently return the sentinel date (so the reader can easily
 know it's bogus).

Having the test be particular about its output helped us find a case
where FreeBSD did not trigger (1), but did trigger (2), by returning a
blanked "struct tm".

I'm open to the argument that (2) is not worth worrying about that much
if it is a hassle to test. But I don't think it is that much hassle
(yet, anyway).

-Peff
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] t4212: handle systems with post-apocalyptic gmtime

2014-03-26 Thread Jeff King
On Wed, Mar 26, 2014 at 03:25:36PM -0400, Jeff King wrote:

> > The primary thing you wanted to achieve by the "gmtime gave us NULL,
> > let's substitute it with an arbitrary value to avoid dereferencing
> > the NULL" change was *not* that we see that same arbitrary value
> > comes out of the system, but that we do not die by attempting to
> > reference the NULL, I think.  Not dying is the primary thing we want
> > to (and we already do) test, no?
> 
> I think there are really two separate behaviors we are testing here (and
> in the surrounding tests):
> 
>   1. Don't segfault if gmtime returns NULL.
> 
>   2. Whenever we cannot process a date (either because gmtime fails, or
>  because we fail before even getting the value to gmtime),
>  consistently return the sentinel date (so the reader can easily
>  know it's bogus).
> 
> Having the test be particular about its output helped us find a case
> where FreeBSD did not trigger (1), but did trigger (2), by returning a
> blanked "struct tm".
> 
> I'm open to the argument that (2) is not worth worrying about that much
> if it is a hassle to test. But I don't think it is that much hassle
> (yet, anyway).

That being said, is the AIX value actually right? I did not look closely
at first, but just assumed that it was vaguely right. But:

  99 / (86400 * 365)

is something like 31 billion years in the future, not 160 million.
A real date calculation will have a few tweaks (leap years, etc), but
that is orders of magnitude off.

So I am not sure that AIX is not actually just giving us utter crap. In
that case, the test is not wrong; it's pickiness is actually finding a
real problem. But I am not sure it is a problem worth solving. I do not
want to get into heuristics deciding whether a particular platform's
gmtime output is crap or not. That pushes this into the realm of "it's
not worth testing", and we should stick to just testing that we did not
segfault.

-Peff
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] t4212: handle systems with post-apocalyptic gmtime

2014-03-26 Thread Jeff King
On Wed, Mar 26, 2014 at 03:33:59PM -0400, Jeff King wrote:

> That being said, is the AIX value actually right? I did not look closely
> at first, but just assumed that it was vaguely right. But:
> 
>   99 / (86400 * 365)
> 
> is something like 31 billion years in the future, not 160 million.
> A real date calculation will have a few tweaks (leap years, etc), but
> that is orders of magnitude off.

Assuming my math is right, then here is the most sensible patch, IMHO.

-- >8 --
Subject: t4212: loosen far-in-future test for AIX

One of the tests in t4212 checks our behavior when we feed
gmtime a date so far in the future that it gives up and
returns NULL. Some implementations, like AIX, may actually
just provide us a bogus result instead.

It's not worth it for us to come up with heuristics that
guess whether the return value is sensible or not. On good
platforms where gmtime reports the problem to us with NULL,
we will print the epoch value. On bad platforms, we will
print garbage.  But our test should be written for the
lowest common denominator so that it passes everywhere.

Reported-by: Charles Bailey 
Signed-off-by: Jeff King 
---
 t/t4212-log-corrupt.sh | 11 +++
 1 file changed, 7 insertions(+), 4 deletions(-)

diff --git a/t/t4212-log-corrupt.sh b/t/t4212-log-corrupt.sh
index 85c6df4..bb843ab 100755
--- a/t/t4212-log-corrupt.sh
+++ b/t/t4212-log-corrupt.sh
@@ -77,11 +77,14 @@ test_expect_success 'date parser recognizes time_t 
overflow' '
 '
 
 # date is within 2^63-1, but enough to choke glibc's gmtime
-test_expect_success 'absurdly far-in-future dates produce sentinel' '
+#
+# Ideally we would check the output to make sure we replaced it with
+# a useful sentinel value, but some platforms will actually hand us back
+# a nonsensical date. It is not worth our time to try to evaluate these
+# dates, so just make sure we didn't segfault or otherwise abort.
+test_expect_success 'absurdly far-in-future dates' '
commit=$(munge_author_date HEAD 99) &&
-   echo "Thu Jan 1 00:00:00 1970 +" >expect &&
-   git log -1 --format=%ad $commit >actual &&
-   test_cmp expect actual
+   git log -1 --format=%ad $commit
 '
 
 test_done
-- 
1.9.1.656.ge8a0637

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v2 07/17] ls-files: add --column

2014-03-26 Thread Eric Sunshine
On Wed, Mar 26, 2014 at 9:48 AM, Nguyễn Thái Ngọc Duy  wrote:
> Signed-off-by: Nguyễn Thái Ngọc Duy 
> ---
>  Documentation/git-ls-files.txt |  6 ++
>  builtin/ls-files.c | 25 +
>  2 files changed, 31 insertions(+)
>
> diff --git a/Documentation/git-ls-files.txt b/Documentation/git-ls-files.txt
> index 5c1b7f3..cd52461 100644
> --- a/Documentation/git-ls-files.txt
> +++ b/Documentation/git-ls-files.txt
> @@ -156,6 +156,12 @@ a space) at the start of each line:
> default to color output, same as `--color=never`. This is the
> default.
>
> +--column[=]::
> +--no-column::
> +   Display files in columns. See configuration variable column.ui
> +   for option syntax.`--column` and `--no-column` without options

Missing space after period.

> +   are equivalent to 'always' and 'never' respectively.
> +
>  \--::
> Do not interpret any more arguments as options.
>
> diff --git a/builtin/ls-files.c b/builtin/ls-files.c
> index 2857b38..335d3b0 100644
> --- a/builtin/ls-files.c
> +++ b/builtin/ls-files.c
> @@ -15,6 +15,7 @@
>  #include "string-list.h"
>  #include "pathspec.h"
>  #include "color.h"
> +#include "column.h"
>
>  static int abbrev;
>  static int show_deleted;
> @@ -29,6 +30,7 @@ static int show_valid_bit;
>  static int line_terminator = '\n';
>  static int debug_mode;
>  static int use_color;
> +static unsigned int colopts;
>
>  static const char *prefix;
>  static int max_prefix_len;
> @@ -39,6 +41,7 @@ static char *ps_matched;
>  static const char *with_tree;
>  static int exc_given;
>  static int exclude_args;
> +static struct string_list output = STRING_LIST_INIT_NODUP;
>
>  static const char *tag_cached = "";
>  static const char *tag_unmerged = "";
> @@ -66,6 +69,10 @@ static void write_name(struct strbuf *sb, const char *name)
>
>  static void strbuf_fputs(struct strbuf *sb, FILE *fp)
>  {
> +   if (column_active(colopts)) {
> +   string_list_append(&output, strbuf_detach(sb, NULL));
> +   return;
> +   }
> fwrite(sb->buf, sb->len, 1, fp);
>  }
>
> @@ -552,6 +559,7 @@ int cmd_ls_files(int argc, const char **argv, const char 
> *cmd_prefix)
> OPT_STRING(0, "with-tree", &with_tree, N_("tree-ish"),
> N_("pretend that paths removed since  are 
> still present")),
> OPT__COLOR(&use_color, N_("show color")),
> +   OPT_COLUMN(0, "column", &colopts, N_("show files in 
> columns")),
> OPT__ABBREV(&abbrev),
> OPT_BOOL(0, "debug", &debug_mode, N_("show debugging data")),
> OPT_END()
> @@ -596,6 +604,18 @@ int cmd_ls_files(int argc, const char **argv, const char 
> *cmd_prefix)
> if (dir.exclude_per_dir)
> exc_given = 1;
>
> +   finalize_colopts(&colopts, -1);
> +   if (explicitly_enable_column(colopts)) {
> +   if (!line_terminator)
> +   die(_("--column and -z are incompatible"));
> +   if (show_resolve_undo)
> +   die(_("--column and --resolve-undo are 
> incompatible"));
> +   if (debug_mode)
> +   die(_("--column and --debug are incompatible"));
> +   }
> +   if (column_active(colopts))
> +   line_terminator = 0;
> +
> if (require_work_tree && !is_inside_work_tree())
> setup_work_tree();
>
> @@ -638,6 +658,11 @@ int cmd_ls_files(int argc, const char **argv, const char 
> *cmd_prefix)
> if (show_resolve_undo)
> show_ru_info();
>
> +   if (column_active(colopts)) {
> +   print_columns(&output, colopts, NULL);
> +   string_list_clear(&output, 0);
> +   }
> +
> if (ps_matched) {
> int bad;
> bad = report_path_error(ps_matched, &pathspec, prefix);
> --
> 1.9.1.345.ga1a145c
>
> --
> To unsubscribe from this list: send the line "unsubscribe git" in
> the body of a message to majord...@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v2 08/17] ls-files: support --max-depth

2014-03-26 Thread Eric Sunshine
On Wed, Mar 26, 2014 at 9:48 AM, Nguyễn Thái Ngọc Duy  wrote:
> Signed-off-by: Nguyễn Thái Ngọc Duy 
> ---
>  Documentation/git-ls-files.txt | 7 +++
>  builtin/ls-files.c | 7 +++
>  2 files changed, 14 insertions(+)
>
> diff --git a/Documentation/git-ls-files.txt b/Documentation/git-ls-files.txt
> index cd52461..3c022eb 100644
> --- a/Documentation/git-ls-files.txt
> +++ b/Documentation/git-ls-files.txt
> @@ -162,6 +162,13 @@ a space) at the start of each line:
> for option syntax.`--column` and `--no-column` without options
> are equivalent to 'always' and 'never' respectively.
>
> +--max-depth ::

Other options in this file are documented as:

--max-depth=::

> +   For each  given on command line, descend at most 
> +   levels of directories. A negative value means no limit.
> +   This option is ignored if  contains active wildcards.
> +   In other words if "a*" matches a directory named "a*",
> +   "*" is matched literally so --max-depth is still effective.

Would it be worthwhile to mention the default?

> +
>  \--::
> Do not interpret any more arguments as options.
>
> diff --git a/builtin/ls-files.c b/builtin/ls-files.c
> index 335d3b0..8eef423 100644
> --- a/builtin/ls-files.c
> +++ b/builtin/ls-files.c
> @@ -503,6 +503,7 @@ static int option_parse_exclude_standard(const struct 
> option *opt,
>  int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix)
>  {
> int require_work_tree = 0, show_tag = 0, i;
> +   int max_depth = -1;
> const char *max_prefix;
> struct dir_struct dir;
> struct exclude_list *el;
> @@ -560,6 +561,9 @@ int cmd_ls_files(int argc, const char **argv, const char 
> *cmd_prefix)
> N_("pretend that paths removed since  are 
> still present")),
> OPT__COLOR(&use_color, N_("show color")),
> OPT_COLUMN(0, "column", &colopts, N_("show files in 
> columns")),
> +   { OPTION_INTEGER, 0, "max-depth", &max_depth, N_("depth"),
> +   N_("descend at most  levels"), PARSE_OPT_NONEG,
> +   NULL, 1 },
> OPT__ABBREV(&abbrev),
> OPT_BOOL(0, "debug", &debug_mode, N_("show debugging data")),
> OPT_END()
> @@ -624,8 +628,11 @@ int cmd_ls_files(int argc, const char **argv, const char 
> *cmd_prefix)
>
> parse_pathspec(&pathspec, 0,
>PATHSPEC_PREFER_CWD |
> +  (max_depth != -1 ? PATHSPEC_MAXDEPTH_VALID : 0) |
>PATHSPEC_STRIP_SUBMODULE_SLASH_CHEAP,
>prefix, argv);
> +   pathspec.max_depth = max_depth;
> +   pathspec.recursive = 1;
>
> /* Find common prefix for all pathspec's */
> max_prefix = common_prefix(&pathspec);
> --
> 1.9.1.345.ga1a145c
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v2 14/19] tree-diff: rework diff_tree interface to be sha1 based

2014-03-26 Thread Kirill Smelkov
On Tue, Mar 25, 2014 at 10:46:32AM -0700, Junio C Hamano wrote:
> Kirill Smelkov  writes:
> 
> > What are the downsides of "__" prefix by the way?
> 
> Aren't these names reserved for compiler/runtime implementations?

Yes, but there are precedents when people don't obey it widely and
in practice everything works :) Let it be something portable anyway -
how about diff_tree_sha1_low() ?

So corrected patch is below. If such suffixing will be accepted, I will
send follow-up patches corrected similiary.

  ( or please pull them from
git://repo.or.cz/git/kirr.git y6/tree-diff-walk-multitree )

Thanks,
Kirill

 8< 
From: Kirill Smelkov 
Date: Mon, 24 Feb 2014 20:21:46 +0400
Subject: [PATCH v3] tree-diff: rework diff_tree interface to be sha1 based

In the next commit this will allow to reduce intermediate calls, when
recursing into subtrees - at that stage we know only subtree sha1, and
it is natural for tree walker to start from that phase. For now we do

diff_tree
show_path
diff_tree_sha1
diff_tree
...

and the change will allow to reduce it to

diff_tree
show_path
diff_tree

Also, it will allow to omit allocating strbuf for each subtree, and just
reuse the common strbuf via playing with its len.

The above-mentioned improvements go in the next 2 patches.

The downside is that try_to_follow_renames(), if active, we cause
re-reading of 2 initial trees, which was negligible based on my timings,
and which is outweighed cogently by the upsides.

NOTE To keep with the current interface and semantics, I needed to
rename the function from diff_tree() to diff_tree_sha1(). As
diff_tree_sha1() was already used, and the function we are talking here
is its more low-level helper, let's use convention for suffixing
such helpers with "_low". So the final renaming is

diff_tree() -> diff_tree_sha1_low()

Signed-off-by: Kirill Smelkov 
---

Changes since v2:

 - renamed __diff_tree_sha1() -> diff_tree_sha1_low() as the former
   overlaps with reserved-for-implementation identifiers namespace.


 tree-diff.c | 60 
 1 file changed, 28 insertions(+), 32 deletions(-)

diff --git a/tree-diff.c b/tree-diff.c
index f137f39..0277c5c 100644
--- a/tree-diff.c
+++ b/tree-diff.c
@@ -141,12 +141,17 @@ static void skip_uninteresting(struct tree_desc *t, 
struct strbuf *base,
}
 }
 
-static int diff_tree(struct tree_desc *t1, struct tree_desc *t2,
-const char *base_str, struct diff_options *opt)
+static int diff_tree_sha1_low(const unsigned char *old, const unsigned char 
*new,
+ const char *base_str, struct diff_options *opt)
 {
+   struct tree_desc t1, t2;
+   void *t1tree, *t2tree;
struct strbuf base;
int baselen = strlen(base_str);
 
+   t1tree = fill_tree_descriptor(&t1, old);
+   t2tree = fill_tree_descriptor(&t2, new);
+
/* Enable recursion indefinitely */
opt->pathspec.recursive = DIFF_OPT_TST(opt, RECURSIVE);
 
@@ -159,39 +164,41 @@ static int diff_tree(struct tree_desc *t1, struct 
tree_desc *t2,
if (diff_can_quit_early(opt))
break;
if (opt->pathspec.nr) {
-   skip_uninteresting(t1, &base, opt);
-   skip_uninteresting(t2, &base, opt);
+   skip_uninteresting(&t1, &base, opt);
+   skip_uninteresting(&t2, &base, opt);
}
-   if (!t1->size && !t2->size)
+   if (!t1.size && !t2.size)
break;
 
-   cmp = tree_entry_pathcmp(t1, t2);
+   cmp = tree_entry_pathcmp(&t1, &t2);
 
/* t1 = t2 */
if (cmp == 0) {
if (DIFF_OPT_TST(opt, FIND_COPIES_HARDER) ||
-   hashcmp(t1->entry.sha1, t2->entry.sha1) ||
-   (t1->entry.mode != t2->entry.mode))
-   show_path(&base, opt, t1, t2);
+   hashcmp(t1.entry.sha1, t2.entry.sha1) ||
+   (t1.entry.mode != t2.entry.mode))
+   show_path(&base, opt, &t1, &t2);
 
-   update_tree_entry(t1);
-   update_tree_entry(t2);
+   update_tree_entry(&t1);
+   update_tree_entry(&t2);
}
 
/* t1 < t2 */
else if (cmp < 0) {
-   show_path(&base, opt, t1, /*t2=*/NULL);
-   update_tree_entry(t1);
+   show_path(&base, opt, &t1, /*t2=*/NULL);
+   update_tree_entry(&t1);
}
 
/* t1 > t2 */
else {
-   show_path(&base, opt, /*t1=*/NULL, t2);
-   update_tree_entry(t2);

Re: [PATCH v2 10/17] Add git-ls, a user friendly version of ls-files and more

2014-03-26 Thread Eric Sunshine
On Wed, Mar 26, 2014 at 9:48 AM, Nguyễn Thái Ngọc Duy  wrote:
> This is more user friendly version of ls-files:
>
> * it's automatically colored and columnized
> * it refreshes the index like all porcelain commands
> * it defaults to non-recursive behavior like ls
> * :(glob) is on by default so '*.c' means a.c but not a/b.c, use
>   '**/*.c' for that.
> * auto pager
>
> Signed-off-by: Nguyễn Thái Ngọc Duy 
> ---
>  .gitignore |  1 +
>  Documentation/config.txt   | 10 ++
>  Documentation/git-ls.txt (new) | 82 
> ++
>  Makefile   |  1 +
>  builtin.h  |  1 +
>  builtin/ls-files.c | 70 
>  command-list.txt   |  1 +
>  git.c  |  1 +
>  8 files changed, 167 insertions(+)
>  create mode 100644 Documentation/git-ls.txt
>
> diff --git a/.gitignore b/.gitignore
> index dc600f9..f91af81 100644
> --- a/.gitignore
> +++ b/.gitignore
> @@ -76,6 +76,7 @@
>  /git-init-db
>  /git-instaweb
>  /git-log
> +/git-ls
>  /git-ls-files
>  /git-ls-remote
>  /git-ls-tree
> diff --git a/Documentation/config.txt b/Documentation/config.txt
> index 6bca55e..87a6dcf 100644
> --- a/Documentation/config.txt
> +++ b/Documentation/config.txt
> @@ -909,6 +909,12 @@ color.status.::
> to red). The values of these variables may be specified as in
> color.branch..
>
> +color.ls::
> +   A boolean to enable/disable color in the output of
> +   linkgit:git-ls[1]. May be set to `always`, `false` (or
> +   `never`) or `auto` (or `true`), in which case colors are used
> +   only when the output is to a terminal. Defaults to false.
> +
>  color.ls.::
> Use customized color for file name colorization. If not set
> and the environment variable LS_COLORS is set, color settings
> @@ -981,6 +987,10 @@ column.clean::
> Specify the layout when list items in `git clean -i`, which always
> shows files and directories in columns. See `column.ui` for details.
>
> +column.ls::
> +   Specify whether to output tag listing in `git ls` in columns.
> +   See `column.ui` for details.
> +
>  column.status::
> Specify whether to output untracked files in `git status` in columns.
> See `column.ui` for details.
> diff --git a/Documentation/git-ls.txt b/Documentation/git-ls.txt
> new file mode 100644
> index 000..67ca522
> --- /dev/null
> +++ b/Documentation/git-ls.txt
> @@ -0,0 +1,82 @@
> +git-ls(1)
> +===
> +
> +NAME
> +
> +git-ls - List files
> +
> +SYNOPSIS
> +
> +[verse]
> +'git ls' (--[cached|deleted|others|ignored|unmerged|modified])*
> +   (-[c|d|o|i|s|u|m])*

Don't you have [...] and (...) transposed? The way it's written, "-"
and "--" are valid optional arguments. You probably meant:

[--(cached|deleted|x|y|z)]...
[-(c|d|x|y|z)]...

> +   [options] [...]

However, you also have the generic [options] here, which covers all of
the above. It probably would make sense to just use [options] and drop
the enumerated list.

> +DESCRIPTION
> +---
> +List files (by default in current working directory) that are in the
> +index. Depending on the chosen options, maybe only modified files in
> +working tree are shown, or untracked files...
> +
> +OPTIONS
> +---
> +-c::
> +--cached::
> +   Show cached files in the output (default)

"in the output" is superfluous. Perhaps drop it from each of the descriptions.

> +-d::
> +--deleted::
> +   Show deleted files in the output

Is this showing only deleted file or including them in the list of
files otherwise displayed? It's not clear from the description. Same
question for the other options.

> +-m::
> +--modified::
> +   Show modified files in the output
> +
> +-o::
> +--others::
> +   Show other (i.e. untracked) files in the output
> +
> +-i::
> +--ignored::
> +   Show only ignored files in the output. When showing files in the
> +   index, print only those matched by an exclude pattern. When
> +   showing "other" files, show only those matched by an exclude
> +   pattern.
> +
> +-u::
> +--unmerged::
> +   Show unmerged files in the output (forces --stage)

This is the only mention of --stage in this document. Not sure what
it's trying to say.

> +--color[=]::
> +   Color file names. The value must be always (default), never,
> +   or auto.

Same problem mentioned in the other patch. Default is "always"...

> +
> +--no-color::
> +   Turn off coloring, even when the configuration file gives the
> +   default to color output, same as `--color=never`. This is the
> +   default.

But default is also "never".

> +
> +--column[=]::
> +--no-column::
> +   Display files in columns. See configuration variable column.ui
> +   for option syntax.`--column` and `--no-column` without options

Missing space after period.

More below.

> +   are equiv

Re: [PATCH] t4212: handle systems with post-apocalyptic gmtime

2014-03-26 Thread Charles Bailey
On Wed, Mar 26, 2014 at 03:40:43PM -0400, Jeff King wrote:
> On Wed, Mar 26, 2014 at 03:33:59PM -0400, Jeff King wrote:
> 
> > That being said, is the AIX value actually right? I did not look closely
> > at first, but just assumed that it was vaguely right. But:
> > 
> >   99 / (86400 * 365)
> > 
> > is something like 31 billion years in the future, not 160 million.
> > A real date calculation will have a few tweaks (leap years, etc), but
> > that is orders of magnitude off.
> 
> Assuming my math is right, then here is the most sensible patch, IMHO.
> 

Perhaps hold onto this one for a little while longer. Splitting things
out from the test is giving me some inconsistent results, there may be
something else going wrong in our environment here.

Charles.
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] t4212: handle systems with post-apocalyptic gmtime

2014-03-26 Thread Jeff King
On Wed, Mar 26, 2014 at 08:36:18PM +, Charles Bailey wrote:

> On Wed, Mar 26, 2014 at 03:40:43PM -0400, Jeff King wrote:
> > On Wed, Mar 26, 2014 at 03:33:59PM -0400, Jeff King wrote:
> > 
> > > That being said, is the AIX value actually right? I did not look closely
> > > at first, but just assumed that it was vaguely right. But:
> > > 
> > >   99 / (86400 * 365)
> > > 
> > > is something like 31 billion years in the future, not 160 million.
> > > A real date calculation will have a few tweaks (leap years, etc), but
> > > that is orders of magnitude off.
> > 
> > Assuming my math is right, then here is the most sensible patch, IMHO.
> > 
> 
> Perhaps hold onto this one for a little while longer. Splitting things
> out from the test is giving me some inconsistent results, there may be
> something else going wrong in our environment here.

By the way, can you confirm that this is a 64-bit system? On a 32-bit
system, we should be triggering different code paths (we fail at the
strtoul level). Those should be checked by the previous tests, but I'd
like to make sure.

-Peff
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] t4212: handle systems with post-apocalyptic gmtime

2014-03-26 Thread Charles Bailey
On Wed, Mar 26, 2014 at 04:38:30PM -0400, Jeff King wrote:
> 
> By the way, can you confirm that this is a 64-bit system? On a 32-bit
> system, we should be triggering different code paths (we fail at the
> strtoul level). Those should be checked by the previous tests, but I'd
> like to make sure.

Yes, we're only building 64-bit at the moment.
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 5/5] log: do not segfault on gmtime errors

2014-03-26 Thread Junio C Hamano
Jeff King  writes:

> On Wed, Mar 26, 2014 at 11:58:49AM -0700, Junio C Hamano wrote:
>
>> > Unlike the FreeBSD thing that René brought up, this is not a problem in
>> > the code, but just in the test. So I think our options are basically:
>> >
>> >   1. Scrap the test as unportable.
>> >
>> >   2. Hard-code a few expected values. I'd be unsurprised if some other
>> >  system comes up with a slightly different date in 162396404, so we
>> >  may end up needing several of these.
>> >
>> > I think I'd lean towards (2), just because it is testing an actual
>> > feature of the code, and I'd like to continue doing so. And while we may
>> > end up with a handful of values, there's probably not _that_ many
>> > independent implementations of gmtime in the wild.
>> 
>> Or "3. Just make sure that 'git log' does not segfault"?
>
> That would not test the FreeBSD case, which does not segfault, but
> returns a bogus sentinel value.
>
> I don't know how important that is. This is such a minor feature that it
> is not worth a lot of maintenance headache in the test. But I also do
> not know if this is going to be the last report, or we will have a bunch
> of other systems that need their own special values put into the test.

I didn't quite realize that your objective of the change was to
signal the failure of gmtime for all implementations, i.e. both (1)
the ones that signal an error by giving NULL back to us and (2) the
ones that fail to signal an error but leave bogus result (FreeBSD,
but it appears AIX might be also giving us another bogus value), by
using a single sane sentinel value.  If we can do that consistently
on every platform, that would indeed be great.

But if that is the case, we should not have to maintain special case
values in the test code, I would think.  The test instead should
expect the output to have that single sentinel value, and if the
workaround code fails to detect a breakage in the platform gmtime(),
the special case logic to catch these platform-specific breakages
should go that "timestamp that cannot be grokked by gmtime---replace
it with a sentinel" logic, no?
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v3 18/25] setup.c: support multi-checkout repo setup

2014-03-26 Thread Junio C Hamano
Duy Nguyen  writes:

> On Tue, Mar 25, 2014 at 08:52:13PM +0700, Duy Nguyen wrote:
>> On Mon, Mar 24, 2014 at 9:52 PM, Torsten Bögershausen  wrote:
>> > Did I report that t1501  fails when  there is a softlink in $PWD ?
>> > /home/tb/projects is a softlink to /disc5/projects/
>> 
>> Yes you did and I forgot. I have fixed it, running test suite and will
>> send the reroll soon.
>
> Junio, it seems you have picked up all minor changes after
> v5. Resending the whole series for one fix seems overkill. Could you
> just --autosquash this one in?

Gladly; thanks for a quick turnaround.

> -- 8< --
> Subject: [PATCH] fixup! setup.c: support multi-checkout repo setup
>
> ---
>  t/t1501-worktree.sh | 8 
>  1 file changed, 4 insertions(+), 4 deletions(-)
>
> diff --git a/t/t1501-worktree.sh b/t/t1501-worktree.sh
> index 2ac4424..e6ac7a4 100755
> --- a/t/t1501-worktree.sh
> +++ b/t/t1501-worktree.sh
> @@ -359,7 +359,7 @@ test_expect_success 'GIT_DIR set (1)' '
>   (
>   cd work &&
>   GIT_DIR=../gitfile git rev-parse --git-common-dir >actual &&
> - echo "$TRASH_DIRECTORY/repo.git" >expect &&
> + test-path-utils real_path "$TRASH_DIRECTORY/repo.git" >expect &&
>   test_cmp expect actual
>   )
>  '
> @@ -370,7 +370,7 @@ test_expect_success 'GIT_DIR set (2)' '
>   (
>   cd work &&
>   GIT_DIR=../gitfile git rev-parse --git-common-dir >actual &&
> - echo "$TRASH_DIRECTORY/repo.git" >expect &&
> + test-path-utils real_path "$TRASH_DIRECTORY/repo.git" >expect &&
>   test_cmp expect actual
>   )
>  '
> @@ -381,7 +381,7 @@ test_expect_success 'Auto discovery' '
>   (
>   cd work &&
>   git rev-parse --git-common-dir >actual &&
> - echo "$TRASH_DIRECTORY/repo.git" >expect &&
> + test-path-utils real_path "$TRASH_DIRECTORY/repo.git" >expect &&
>   test_cmp expect actual &&
>   echo haha >data1 &&
>   git add data1 &&
> @@ -399,7 +399,7 @@ test_expect_success '$GIT_DIR/common overrides 
> core.worktree' '
>   (
>   cd work &&
>   git rev-parse --git-common-dir >actual &&
> - echo "$TRASH_DIRECTORY/repo.git" >expect &&
> + test-path-utils real_path "$TRASH_DIRECTORY/repo.git" >expect &&
>   test_cmp expect actual &&
>   echo haha >data2 &&
>   git add data2 &&
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 5/5] log: do not segfault on gmtime errors

2014-03-26 Thread Jeff King
On Wed, Mar 26, 2014 at 02:01:21PM -0700, Junio C Hamano wrote:

> > I don't know how important that is. This is such a minor feature that it
> > is not worth a lot of maintenance headache in the test. But I also do
> > not know if this is going to be the last report, or we will have a bunch
> > of other systems that need their own special values put into the test.
> 
> I didn't quite realize that your objective of the change was to
> signal the failure of gmtime for all implementations,

I didn't realize it at the time I wrote the test, either. It was my goal
to recognize such failures, but I didn't now at the time that there were
failures that would be signaled by anything besides a NULL return.

> the ones that signal an error by giving NULL back to us and (2) the
> ones that fail to signal an error but leave bogus result (FreeBSD,
> but it appears AIX might be also giving us another bogus value), by
> using a single sane sentinel value.  If we can do that consistently
> on every platform, that would indeed be great.

Agreed. I am not sure we can do so. For FreeBSD, I think it is not hard.
I am not sure what the pattern is for AIX. I am hoping Charles will
reveal some pattern, but there may not be one.

> But if that is the case, we should not have to maintain special case
> values in the test code, I would think.

Right. All of my suggestions to accommodate special values in the test
were assuming that the system gmtime was smarter than we are. That it
produced a good value for this crazy time and _didn't_ fail.

But after having done the basic math, I don't think that is what is
going on here.

> The test instead should expect the output to have that single sentinel
> value, and if the workaround code fails to detect a breakage in the
> platform gmtime(), the special case logic to catch these
> platform-specific breakages should go that "timestamp that cannot be
> grokked by gmtime---replace it with a sentinel" logic, no?

Yes, exactly. That is the preferable solution, if we can come up with
such logic. Personally I am not optimistic.

The fallback is to accept that we cannot cover all cases, and just
loosen the test (i.e., the second patch I posted today).

-Peff
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH] apply --ignore-space-change: lines with and without leading whitespaces do not match

2014-03-26 Thread Junio C Hamano
The fuzzy_matchlines() function is used when attempting to resurrect
a patch that is whitespace-damaged, or when applying a patch that
was produced against an old codebase to the codebase after
indentation change.

The patch may want to change a line "a_bc" ("_" is used throught
this description for a whitespace to make it stand out) in the
original into something else, and we may not find "a_bc" in the
current source, but there may be "a__bc" (two spaces instead of one
the whitespace-damaged patch claims to expect).  By ignoring the
amount of whitespaces, it forces "git apply" to consider that "a_bc"
in the broken patch meant to refer to "a__bc" in reality.

However, the implementation special cases a run of whitespaces at
the beginning of a line and makes "abc" match "_abc", even though a
whitespace in the middle of string never matches a 0-width gap,
e.g. "a_bc" does not match "abc".  A run of whitespace at the end of
one string does not match a 0-width end of line on the other line,
either, e.g. "abc_" does not match "abc".

Fix this inconsistency by making the code skip leading whitespaces
only when both strings begin with a whitespace.  This makes the
option mean the same as the option of the same name in "diff" and
"git diff".

Note that I am not sure if anybody sane should use this option in
the first place.  The fuzzy match logic may be able to find the
original line that the patch author may have meant to touch because
it does not fully trust what the original lines say (i.e. context
lines prefixed by " " and old lines prefixed by "-" does not have to
exactly match the contents the patch is applied to).  There is no
reason for us to trust what the replacement lines (i.e. new lines
prefixed by "+") say, either, but with this option enabled, we end
up copying these new lines with suspicious whitespace distributions
literally into the patched result.  But as long as we keep it, we
should make it do its insane thing consistently.

Signed-off-by: Junio C Hamano 
---
 builtin/apply.c| 12 +++-
 t/t4107-apply-ignore-whitespace.sh | 12 
 2 files changed, 11 insertions(+), 13 deletions(-)

diff --git a/builtin/apply.c b/builtin/apply.c
index 0189523..8b9d3de 100644
--- a/builtin/apply.c
+++ b/builtin/apply.c
@@ -300,11 +300,13 @@ static int fuzzy_matchlines(const char *s1, size_t n1,
while ((*last2 == '\r') || (*last2 == '\n'))
last2--;
 
-   /* skip leading whitespace */
-   while (isspace(*s1) && (s1 <= last1))
-   s1++;
-   while (isspace(*s2) && (s2 <= last2))
-   s2++;
+   /* skip leading whitespaces, if both begin with whitespace */
+   if (s1 <= last1 && s2 <= last2 && isspace(*s1) && isspace(*s2)) {
+   while (isspace(*s1) && (s1 <= last1))
+   s1++;
+   while (isspace(*s2) && (s2 <= last2))
+   s2++;
+   }
/* early return if both lines are empty */
if ((s1 > last1) && (s2 > last2))
return 1;
diff --git a/t/t4107-apply-ignore-whitespace.sh 
b/t/t4107-apply-ignore-whitespace.sh
index b04fc8f..9e29b52 100755
--- a/t/t4107-apply-ignore-whitespace.sh
+++ b/t/t4107-apply-ignore-whitespace.sh
@@ -111,7 +111,6 @@ sed -e 's/T//g' > main.c.final <<\EOF
 #include 
 
 void print_int(int num);
-T/* a comment */
 int func(int num);
 
 int main() {
@@ -154,7 +153,8 @@ test_expect_success 'patch2 reverse applies with 
--ignore-space-change' '
 git config apply.ignorewhitespace change
 
 test_expect_success 'patch2 applies (apply.ignorewhitespace = change)' '
-   git apply patch2.patch
+   git apply patch2.patch &&
+   test_cmp main.c.final main.c
 '
 
 test_expect_success 'patch3 fails (missing string at EOL)' '
@@ -165,12 +165,8 @@ test_expect_success 'patch4 fails (missing EOL at EOF)' '
test_must_fail git apply patch4.patch
 '
 
-test_expect_success 'patch5 applies (leading whitespace)' '
-   git apply patch5.patch
-'
-
-test_expect_success 'patches do not mangle whitespace' '
-   test_cmp main.c main.c.final
+test_expect_success 'patch5 fails (leading whitespace differences matter)' '
+   test_must_fail git apply patch5.patch
 '
 
 test_expect_success 're-create file (with --ignore-whitespace)' '
-- 
1.9.1-497-g6f5ca27

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] t4212: handle systems with post-apocalyptic gmtime

2014-03-26 Thread Charles Bailey
On Wed, Mar 26, 2014 at 03:33:59PM -0400, Jeff King wrote:
> 
> That being said, is the AIX value actually right? I did not look closely
> at first, but just assumed that it was vaguely right. But:
> 
>   99 / (86400 * 365)
> 
> is something like 31 billion years in the future, not 160 million.
> A real date calculation will have a few tweaks (leap years, etc), but
> that is orders of magnitude off.

Well, this is embarrassing, while moving this through the corporate
firewall (aka typing on one machine while looking at another), I
munged the date. It still doesn't seem right but at least you can now
see the actual data.

I stopped the test with --immediate and found the dangling commit that
the test created and dumped it with the previous version of Git (well
a 1.8.5.5 build)

  ibm: trash directory.t4212-log-corrupt $ git log -1 --pretty=raw 
1fc17e734e4487c31bdfe05bb3d15618b69c4dca
  commit 1fc17e734e4487c31bdfe05bb3d15618b69c4dca
  tree 64fd3796c57084e7b8cbae358ce37970b8e954f6
  author A U Thor  99 -0700
  committer C O Mitter  1112911993 -0700

  foo

  ibm: trash directory.t4212-log-corrupt $ git log -1 
1fc17e734e4487c31bdfe05bb3d15618b69c4dca
  commit 1fc17e734e4487c31bdfe05bb3d15618b69c4dca
  Author: A U Thor 
  Date:   Thu Oct 24 18:46:39 1623969404 -0700

  foo

Same commit but dumped from a linux machine:

  linux: trash directory.t4212-log-corrupt $ git log -1 
1fc17e734e4487c31bdfe05bb3d15618b69c4dca
  commit 1fc17e734e4487c31bdfe05bb3d15618b69c4dca
  Author: A U Thor 
  Date:   (null)

  foo

Charles.
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v2 14/19] tree-diff: rework diff_tree interface to be sha1 based

2014-03-26 Thread Junio C Hamano
Kirill Smelkov  writes:

> On Tue, Mar 25, 2014 at 10:46:32AM -0700, Junio C Hamano wrote:
>> Kirill Smelkov  writes:
>> 
>> > What are the downsides of "__" prefix by the way?
>> 
>> Aren't these names reserved for compiler/runtime implementations?
>
> Yes, but there are precedents when people don't obey it widely and
> in practice everything works :)

I think you are alluding to the practice in the Linux kernel, but
their requirement is vastly different---their product do not even
link with libc and they always compile with specific selected
versions of gcc, no?

> Let it be something portable anyway -
> how about diff_tree_sha1_low() ?

Sure.

As this is a file-scope static, I do not think the exact naming
matters that much.  Just FYI, we seem to use ll_ prefix (standing
for low-level) in some places.

Thanks.
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v2 19/27] refs: Add a concept of a reference transaction

2014-03-26 Thread Michael Haggerty
On 03/26/2014 07:39 PM, Brad King wrote:
> On 03/24/2014 01:56 PM, Michael Haggerty wrote:
>> +void ref_transaction_update(struct ref_transaction *transaction,
>> +const char *refname,
>> +unsigned char *new_sha1, unsigned char *old_sha1,
>> +int flags, int have_old);
> [snip]
>> +void ref_transaction_create(struct ref_transaction *transaction,
>> +const char *refname,
>> +unsigned char *new_sha1,
>> +int flags);
> [snip]
>> +void ref_transaction_delete(struct ref_transaction *transaction,
>> +const char *refname,
>> +unsigned char *old_sha1,
>> +int flags, int have_old);
> 
> Perhaps we also need:
> 
> void ref_transaction_verify(struct ref_transaction *transaction,
>   const char *refname,
>   unsigned char *old_sha1,
>   int flags, int have_old);
> 
> as equivalent to the "verify" command in "update-ref --stdin"?

Yes.  That's already on my todo list for a future batch of patches.  But
first I was going to beef up the ref_update structure to handle verify
actions directly rather than as updates with oldvalue==newvalue,
probably by turning has_old into a flag with HAS_OLD and HAS_NEW bits.

Michael

-- 
Michael Haggerty
mhag...@alum.mit.edu
http://softwareswirl.blogspot.com/
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v2 00/27] Clean up update-refs --stdin and implement ref_transaction

2014-03-26 Thread Michael Haggerty
On 03/26/2014 07:39 PM, Brad King wrote:
> On 03/24/2014 01:56 PM, Michael Haggerty wrote:
>> Changes relative to v1:
>>
>> * Rename the functions associated with ref_transactions to be more
>>   reminiscent of database transactions:
>>
>>   * create_ref_transaction() -> ref_transaction_begin()
>>   * free_ref_transaction() -> ref_transaction_rollback()
>>   * queue_update_ref() -> ref_transaction_update()
>>   * queue_create_ref() -> ref_transaction_create()
>>   * queue_delete_ref() -> ref_transaction_delete()
>>   * commit_ref_transaction() -> ref_transaction_commit()
> 
> Those new names look better.
> 
>> * Fix backwards compatibility of "git update-ref --stdin -z"'s
>>   handling of the "create" command: allow  to be the empty
>>   string, treating it the same zeros.  But deprecate this usage.
> 
> The changes related to that look good.  The new documentation is
> much clearer than my old wording.
> 
> Series v2 looks good to me except for my responses to individual
> commits.

Thanks a lot for the review.  Your other two comments are correct, of
course, and I will fix them if there needs to be a re-roll.

Michael

-- 
Michael Haggerty
mhag...@alum.mit.edu
http://softwareswirl.blogspot.com/
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] t4212: handle systems with post-apocalyptic gmtime

2014-03-26 Thread Jeff King
On Wed, Mar 26, 2014 at 09:22:27PM +, Charles Bailey wrote:

> On Wed, Mar 26, 2014 at 03:33:59PM -0400, Jeff King wrote:
> > 
> > That being said, is the AIX value actually right? I did not look closely
> > at first, but just assumed that it was vaguely right. But:
> > 
> >   99 / (86400 * 365)
> > 
> > is something like 31 billion years in the future, not 160 million.
> > A real date calculation will have a few tweaks (leap years, etc), but
> > that is orders of magnitude off.
> 
> Well, this is embarrassing, while moving this through the corporate
> firewall (aka typing on one machine while looking at another), I
> munged the date. It still doesn't seem right but at least you can now
> see the actual data.

Hmm, so the year you got is actually: 1623969404. That still seems off
to me by a factor 20. I don't know if this is really worth digging into
that much further, but I wonder what you would get for timestamps of:

  9
  
  999
  etc.

Do we start generating weird values at some particular size? Or is AIX
gmtime really more clever than I am, and is accounting for wobble of the
Earth or something over the next billion years?

-Peff
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v8 03/12] Move lower case functions into wrapper.c

2014-03-26 Thread Christian Couder
The lowercase() function from config.c and the xstrdup_tolower()
function from daemon.c can benefit from being moved to the same
place because this way the latter can use the former.

Also let's make them available globally so we can use them from
other places like trailer.c.

Signed-off-by: Christian Couder 
---
 config.c  |  6 --
 daemon.c  |  8 
 git-compat-util.h |  4 
 wrapper.c | 14 ++
 4 files changed, 18 insertions(+), 14 deletions(-)

diff --git a/config.c b/config.c
index 314d8ee..dde128e 100644
--- a/config.c
+++ b/config.c
@@ -146,12 +146,6 @@ int git_config_include(const char *var, const char *value, 
void *data)
return ret;
 }
 
-static void lowercase(char *p)
-{
-   for (; *p; p++)
-   *p = tolower(*p);
-}
-
 void git_config_push_parameter(const char *text)
 {
struct strbuf env = STRBUF_INIT;
diff --git a/daemon.c b/daemon.c
index eba1255..f9c63e9 100644
--- a/daemon.c
+++ b/daemon.c
@@ -475,14 +475,6 @@ static void make_service_overridable(const char *name, int 
ena)
die("No such service %s", name);
 }
 
-static char *xstrdup_tolower(const char *str)
-{
-   char *p, *dup = xstrdup(str);
-   for (p = dup; *p; p++)
-   *p = tolower(*p);
-   return dup;
-}
-
 static void parse_host_and_port(char *hostport, char **host,
char **port)
 {
diff --git a/git-compat-util.h b/git-compat-util.h
index 614a5e9..2397706 100644
--- a/git-compat-util.h
+++ b/git-compat-util.h
@@ -727,4 +727,8 @@ void warn_on_inaccessible(const char *path);
 /* Get the passwd entry for the UID of the current process. */
 struct passwd *xgetpwuid_self(void);
 
+/* Lowercase strings */
+extern void lowercase(char *str);
+extern char *xstrdup_tolower(const char *str);
+
 #endif
diff --git a/wrapper.c b/wrapper.c
index 0cc5636..c46026a 100644
--- a/wrapper.c
+++ b/wrapper.c
@@ -455,3 +455,17 @@ struct passwd *xgetpwuid_self(void)
errno ? strerror(errno) : _("no such user"));
return pw;
 }
+
+void lowercase(char *p)
+{
+   for (; *p; p++)
+   *p = tolower(*p);
+}
+
+char *xstrdup_tolower(const char *str)
+{
+   char *dup = xstrdup(str);
+   lowercase(dup);
+   return dup;
+}
+
-- 
1.9.0.164.g3aa33cd.dirty


--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v8 06/12] trailer: parse trailers from stdin

2014-03-26 Thread Christian Couder
Read trailers from stdin, parse them and put the result into a doubly linked
list.

Signed-off-by: Christian Couder 
---
 trailer.c | 76 +++
 1 file changed, 76 insertions(+)

diff --git a/trailer.c b/trailer.c
index 1871843..3993840 100644
--- a/trailer.c
+++ b/trailer.c
@@ -50,6 +50,14 @@ static size_t alnum_len(const char *buf, size_t len)
return len;
 }
 
+static inline int contains_only_spaces(const char *str)
+{
+   const char *s = str;
+   while (*s && isspace(*s))
+   s++;
+   return !*s;
+}
+
 static void free_trailer_item(struct trailer_item *item)
 {
free(item->conf.name);
@@ -501,3 +509,71 @@ static struct trailer_item *process_command_line_args(int 
argc, const char **arg
 
return arg_tok_first;
 }
+
+static struct strbuf **read_stdin(void)
+{
+   struct strbuf **lines;
+   struct strbuf sb = STRBUF_INIT;
+
+   if (strbuf_read(&sb, fileno(stdin), 0) < 0)
+   die_errno(_("could not read from stdin"));
+
+   lines = strbuf_split(&sb, '\n');
+
+   strbuf_release(&sb);
+
+   return lines;
+}
+
+/*
+ * Return the the (0 based) index of the first trailer line
+ * or the line count if there are no trailers.
+ */
+static int find_trailer_start(struct strbuf **lines)
+{
+   int start, empty = 1, count = 0;
+
+   /* Get the line count */
+   while (lines[count])
+   count++;
+
+   /*
+* Get the start of the trailers by looking starting from the end
+* for a line with only spaces before lines with one ':'.
+*/
+   for (start = count - 1; start >= 0; start--) {
+   if (contains_only_spaces(lines[start]->buf)) {
+   if (empty)
+   continue;
+   return start + 1;
+   }
+   if (strchr(lines[start]->buf, ':')) {
+   if (empty)
+   empty = 0;
+   continue;
+   }
+   return count;
+   }
+
+   return empty ? count : start + 1;
+}
+
+static void process_stdin(struct trailer_item **in_tok_first,
+ struct trailer_item **in_tok_last)
+{
+   struct strbuf **lines = read_stdin();
+   int start = find_trailer_start(lines);
+   int i;
+
+   /* Print non trailer lines as is */
+   for (i = 0; lines[i] && i < start; i++)
+   printf("%s", lines[i]->buf);
+
+   /* Parse trailer lines */
+   for (i = start; lines[i]; i++) {
+   struct trailer_item *new = create_trailer_item(lines[i]->buf);
+   add_trailer_item(in_tok_first, in_tok_last, new);
+   }
+
+   strbuf_list_free(lines);
+}
-- 
1.9.0.164.g3aa33cd.dirty


--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v8 00/12] Add interpret-trailers builtin

2014-03-26 Thread Christian Couder
This patch series implements a new command:

git interpret-trailers

and an infrastructure to process trailers that can be reused,
for example in "commit.c".

1) Rationale:

This command should help with RFC 822 style headers, called
"trailers", that are found at the end of commit messages.

(Note that these headers do not follow and are not intended to
follow many rules that are in RFC 822. For example they do not
follow the line breaking rules, the encoding rules and probably
many other rules.)

For a long time, these trailers have become a de facto standard
way to add helpful information into commit messages.

Until now git commit has only supported the well known
"Signed-off-by: " trailer, that is used by many projects like
the Linux kernel and Git.

It is better to implement features for these trailers first in a
new command rather than in builtin/commit.c, because this way the
prepare-commit-msg and commit-msg hooks can reuse this command.
 
2) Current state:

Currently the usage string of this command is:

git interpret-trailers [--trim-empty] [([(=|:)])...]

The following features are implemented:

- the result is printed on stdout
- the [[=]>] arguments are interpreted
- a commit message read from stdin is interpreted
- the "trailer..key" options in the config are interpreted
- the "trailer..where" options are interpreted
- the "trailer..ifExist" options are interpreted
- the "trailer..ifMissing" options are interpreted
- the "trailer..command" config works
- $ARG can be used in commands
- there are some tests
- there is some documentation

The following features are planned but not yet implemented:
- add more tests related to commands
- add examples in documentation
- integration with "git commit"

Possible improvements:
- support GIT_COMMIT_PROTO env variable in commands

3) Changes since version 7, thanks to Junio:

* improved handling of empty trailer token
* clearer way to create 'expected' files in tests
* other small test cleanups
* improved commit message
* new way to parse config keys
* strcasecmp() is not used anymore in some config related functions
Some values from the config file are lowercased instead.
To enable that a new patch (3/12) is introduced to rationalize
lowercase related functions. I am not very happy with these
changes.


Christian Couder (12):
  Add data structures and basic functions for commit trailers
  trailer: process trailers from stdin and arguments
  Move lower case functions into wrapper.c
  trailer: read and process config information
  trailer: process command line trailer arguments
  trailer: parse trailers from stdin
  trailer: put all the processing together and print
  trailer: add interpret-trailers command
  trailer: add tests for "git interpret-trailers"
  trailer: execute command from 'trailer..command'
  trailer: add tests for commands in config file
  Documentation: add documentation for 'git interpret-trailers'

 .gitignore   |   1 +
 Documentation/git-interpret-trailers.txt | 123 ++
 Makefile |   2 +
 builtin.h|   1 +
 builtin/interpret-trailers.c |  33 ++
 config.c |   6 -
 daemon.c |   8 -
 git-compat-util.h|   4 +
 git.c|   1 +
 t/t7513-interpret-trailers.sh| 407 ++
 trailer.c| 691 +++
 trailer.h|   6 +
 wrapper.c|  14 +
 13 files changed, 1283 insertions(+), 14 deletions(-)
 create mode 100644 Documentation/git-interpret-trailers.txt
 create mode 100644 builtin/interpret-trailers.c
 create mode 100755 t/t7513-interpret-trailers.sh
 create mode 100644 trailer.c
 create mode 100644 trailer.h

-- 
1.9.0.164.g3aa33cd.dirty

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v8 04/12] trailer: read and process config information

2014-03-26 Thread Christian Couder
Read the configuration to get trailer information, and then process
it and storing it in a doubly linked list.

The config information is stored in the list whose first item is
pointed to by:

static struct trailer_item *first_conf_item;

Signed-off-by: Christian Couder 
---
 trailer.c | 153 ++
 1 file changed, 153 insertions(+)

diff --git a/trailer.c b/trailer.c
index 52108c2..b5a0943 100644
--- a/trailer.c
+++ b/trailer.c
@@ -25,6 +25,8 @@ struct trailer_item {
struct conf_info conf;
 };
 
+static struct trailer_item *first_conf_item;
+
 static int same_token(struct trailer_item *a, struct trailer_item *b, int 
alnum_len)
 {
return !strncasecmp(a->token, b->token, alnum_len);
@@ -245,3 +247,154 @@ static void process_trailers_lists(struct trailer_item 
**in_tok_first,
apply_arg_if_missing(in_tok_first, in_tok_last, arg_tok);
}
 }
+
+static int set_where(struct conf_info *item, const char *value)
+{
+   if (!strcmp("after", value))
+   item->where = WHERE_AFTER;
+   else if (!strcmp("before", value))
+   item->where = WHERE_BEFORE;
+   else
+   return -1;
+   return 0;
+}
+
+static int set_if_exists(struct conf_info *item, const char *value)
+{
+   if (!strcmp("addifdifferent", value))
+   item->if_exists = EXISTS_ADD_IF_DIFFERENT;
+   else if (!strcmp("addifdifferentneighbor", value))
+   item->if_exists = EXISTS_ADD_IF_DIFFERENT_NEIGHBOR;
+   else if (!strcmp("add", value))
+   item->if_exists = EXISTS_ADD;
+   else if (!strcmp("overwrite", value))
+   item->if_exists = EXISTS_OVERWRITE;
+   else if (!strcmp("donothing", value))
+   item->if_exists = EXISTS_DO_NOTHING;
+   else
+   return -1;
+   return 0;
+}
+
+static int set_if_missing(struct conf_info *item, const char *value)
+{
+   if (!strcmp("donothing", value))
+   item->if_missing = MISSING_DO_NOTHING;
+   else if (!strcmp("add", value))
+   item->if_missing = MISSING_ADD;
+   else
+   return -1;
+   return 0;
+}
+
+static struct trailer_item *get_conf_item(const char *name)
+{
+   struct trailer_item *item;
+   struct trailer_item *previous;
+
+   /* Look up item with same name */
+   for (previous = NULL, item = first_conf_item;
+item;
+previous = item, item = item->next) {
+   if (!strcasecmp(item->conf.name, name))
+   return item;
+   }
+
+   /* Item does not already exists, create it */
+   item = xcalloc(sizeof(struct trailer_item), 1);
+   item->conf.name = xstrdup(name);
+
+   if (!previous)
+   first_conf_item = item;
+   else {
+   previous->next = item;
+   item->previous = previous;
+   }
+
+   return item;
+}
+
+enum trailer_info_type { TRAILER_KEY, TRAILER_COMMAND, TRAILER_WHERE,
+TRAILER_IF_EXISTS, TRAILER_IF_MISSING };
+
+static struct {
+   const char *name;
+   enum trailer_info_type type;
+} trailer_config_items[] = {
+   { "key", TRAILER_KEY },
+   { "command", TRAILER_COMMAND },
+   { "where", TRAILER_WHERE },
+   { "ifexists", TRAILER_IF_EXISTS },
+   { "ifmissing", TRAILER_IF_MISSING }
+};
+
+static int git_trailer_config(const char *conf_key, const char *value, void 
*cb)
+{
+   const char *trailer_item, *variable_name;
+   struct trailer_item *item;
+   struct conf_info *conf;
+   char *name = NULL;
+   enum trailer_info_type type;
+   char *lowercase_value;
+   int i;
+
+   trailer_item = skip_prefix(conf_key, "trailer.");
+   if (!trailer_item)
+   return 0;
+
+   variable_name = strrchr(trailer_item, '.');
+   if (!variable_name) {
+   warning(_("two level trailer config variable %s"), conf_key);
+   return 0;
+   }
+
+   variable_name++;
+   for (i = 0; i < ARRAY_SIZE(trailer_config_items); i++) {
+   if (strcmp(trailer_config_items[i].name, variable_name))
+   continue;
+   name = xstrndup(trailer_item,  variable_name - trailer_item -1);
+   type = trailer_config_items[i].type;
+   break;
+   }
+
+   if (!name)
+   return 0;
+
+   item = get_conf_item(name);
+   conf = &item->conf;
+   free(name);
+
+   switch (type) {
+   case TRAILER_KEY:
+   if (conf->key)
+   warning(_("more than one %s"), conf_key);
+   conf->key = xstrdup(value);
+   break;
+   case TRAILER_COMMAND:
+   if (conf->command)
+   warning(_("more than one %s"), conf_key);
+   conf->command = xstrdup(value);
+   break;
+   case TRAILER_WHERE:
+  

[PATCH v8 07/12] trailer: put all the processing together and print

2014-03-26 Thread Christian Couder
This patch adds the process_trailers() function that
calls all the previously added processing functions
and then prints the results on the standard output.

Signed-off-by: Christian Couder 
---
 trailer.c | 49 +
 trailer.h |  6 ++
 2 files changed, 55 insertions(+)
 create mode 100644 trailer.h

diff --git a/trailer.c b/trailer.c
index 3993840..5bb29ae 100644
--- a/trailer.c
+++ b/trailer.c
@@ -1,4 +1,5 @@
 #include "cache.h"
+#include "trailer.h"
 /*
  * Copyright (c) 2013, 2014 Christian Couder 
  */
@@ -68,6 +69,26 @@ static void free_trailer_item(struct trailer_item *item)
free(item);
 }
 
+static void print_tok_val(const char *tok, const char *val)
+{
+   char c = tok[strlen(tok) - 1];
+   if (isalnum(c))
+   printf("%s: %s\n", tok, val);
+   else if (isspace(c) || c == '#')
+   printf("%s%s\n", tok, val);
+   else
+   printf("%s %s\n", tok, val);
+}
+
+static void print_all(struct trailer_item *first, int trim_empty)
+{
+   struct trailer_item *item;
+   for (item = first; item; item = item->next) {
+   if (!trim_empty || strlen(item->value) > 0)
+   print_tok_val(item->token, item->value);
+   }
+}
+
 static void add_arg_to_input_list(struct trailer_item *in_tok,
  struct trailer_item *arg_tok)
 {
@@ -577,3 +598,31 @@ static void process_stdin(struct trailer_item 
**in_tok_first,
 
strbuf_list_free(lines);
 }
+
+static void free_all(struct trailer_item **first)
+{
+   while (*first) {
+   struct trailer_item *item = remove_first(first);
+   free_trailer_item(item);
+   }
+}
+
+void process_trailers(int trim_empty, int argc, const char **argv)
+{
+   struct trailer_item *in_tok_first = NULL;
+   struct trailer_item *in_tok_last = NULL;
+   struct trailer_item *arg_tok_first;
+
+   git_config(git_trailer_config, NULL);
+
+   /* Print the non trailer part of stdin */
+   process_stdin(&in_tok_first, &in_tok_last);
+
+   arg_tok_first = process_command_line_args(argc, argv);
+
+   process_trailers_lists(&in_tok_first, &in_tok_last, &arg_tok_first);
+
+   print_all(in_tok_first, trim_empty);
+
+   free_all(&in_tok_first);
+}
diff --git a/trailer.h b/trailer.h
new file mode 100644
index 000..9323b1e
--- /dev/null
+++ b/trailer.h
@@ -0,0 +1,6 @@
+#ifndef TRAILER_H
+#define TRAILER_H
+
+void process_trailers(int trim_empty, int argc, const char **argv);
+
+#endif /* TRAILER_H */
-- 
1.9.0.164.g3aa33cd.dirty


--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v8 10/12] trailer: execute command from 'trailer..command'

2014-03-26 Thread Christian Couder
Let the user specify a command that will give on its standard output
the value to use for the specified trailer.

Signed-off-by: Christian Couder 
---
 trailer.c | 63 +++
 1 file changed, 63 insertions(+)

diff --git a/trailer.c b/trailer.c
index 5bb29ae..eeb2f86 100644
--- a/trailer.c
+++ b/trailer.c
@@ -1,4 +1,5 @@
 #include "cache.h"
+#include "run-command.h"
 #include "trailer.h"
 /*
  * Copyright (c) 2013, 2014 Christian Couder 
@@ -13,11 +14,14 @@ struct conf_info {
char *name;
char *key;
char *command;
+   unsigned command_uses_arg : 1;
enum action_where where;
enum action_if_exists if_exists;
enum action_if_missing if_missing;
 };
 
+#define TRAILER_ARG_STRING "$ARG"
+
 struct trailer_item {
struct trailer_item *previous;
struct trailer_item *next;
@@ -59,6 +63,13 @@ static inline int contains_only_spaces(const char *str)
return !*s;
 }
 
+static inline void strbuf_replace(struct strbuf *sb, const char *a, const char 
*b)
+{
+   const char *ptr = strstr(sb->buf, a);
+   if (ptr)
+   strbuf_splice(sb, ptr - sb->buf, strlen(a), b, strlen(b));
+}
+
 static void free_trailer_item(struct trailer_item *item)
 {
free(item->conf.name);
@@ -403,6 +414,7 @@ static int git_trailer_config(const char *conf_key, const 
char *value, void *cb)
if (conf->command)
warning(_("more than one %s"), conf_key);
conf->command = xstrdup(value);
+   conf->command_uses_arg = !!strstr(conf->command, 
TRAILER_ARG_STRING);
break;
case TRAILER_WHERE:
lowercase_value = xstrdup_tolower(value);
@@ -445,6 +457,44 @@ static int parse_trailer(struct strbuf *tok, struct strbuf 
*val, const char *tra
return 0;
 }
 
+static int read_from_command(struct child_process *cp, struct strbuf *buf)
+{
+   if (run_command(cp))
+   return error("running trailer command '%s' failed", 
cp->argv[0]);
+   if (strbuf_read(buf, cp->out, 1024) < 1)
+   return error("reading from trailer command '%s' failed", 
cp->argv[0]);
+   strbuf_trim(buf);
+   return 0;
+}
+
+static const char *apply_command(const char *command, const char *arg)
+{
+   struct strbuf cmd = STRBUF_INIT;
+   struct strbuf buf = STRBUF_INIT;
+   struct child_process cp;
+   const char *argv[] = {NULL, NULL};
+   const char *result = "";
+
+   strbuf_addstr(&cmd, command);
+   if (arg)
+   strbuf_replace(&cmd, TRAILER_ARG_STRING, arg);
+
+   argv[0] = cmd.buf;
+   memset(&cp, 0, sizeof(cp));
+   cp.argv = argv;
+   cp.env = local_repo_env;
+   cp.no_stdin = 1;
+   cp.out = -1;
+   cp.use_shell = 1;
+
+   if (read_from_command(&cp, &buf))
+   strbuf_release(&buf);
+   else
+   result = strbuf_detach(&buf, NULL);
+
+   strbuf_release(&cmd);
+   return result;
+}
 
 static void duplicate_conf(struct conf_info *dst, struct conf_info *src)
 {
@@ -467,6 +517,10 @@ static struct trailer_item *new_trailer_item(struct 
trailer_item *conf_item,
duplicate_conf(&new->conf, &conf_item->conf);
new->token = xstrdup(conf_item->conf.key);
free(tok);
+   if (conf_item->conf.command_uses_arg || !val) {
+   new->value = apply_command(conf_item->conf.command, 
val);
+   free(val);
+   }
} else
new->token = tok;
 
@@ -522,12 +576,21 @@ static struct trailer_item *process_command_line_args(int 
argc, const char **arg
int i;
struct trailer_item *arg_tok_first = NULL;
struct trailer_item *arg_tok_last = NULL;
+   struct trailer_item *item;
 
for (i = 0; i < argc; i++) {
struct trailer_item *new = create_trailer_item(argv[i]);
add_trailer_item(&arg_tok_first, &arg_tok_last, new);
}
 
+   /* Add conf commands that don't use $ARG */
+   for (item = first_conf_item; item; item = item->next) {
+   if (item->conf.command && !item->conf.command_uses_arg) {
+   struct trailer_item *new = new_trailer_item(item, NULL, 
NULL);
+   add_trailer_item(&arg_tok_first, &arg_tok_last, new);
+   }
+   }
+
return arg_tok_first;
 }
 
-- 
1.9.0.164.g3aa33cd.dirty


--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v8 02/12] trailer: process trailers from stdin and arguments

2014-03-26 Thread Christian Couder
Implement the logic to process trailers from stdin and arguments.

At the beginning trailers from stdin are in their own in_tok
doubly linked list, and trailers from arguments are in their own
arg_tok doubly linked list.

The lists are traversed and when an arg_tok should be "applied",
it is removed from its list and inserted into the in_tok list.

Signed-off-by: Christian Couder 
---
 trailer.c | 198 ++
 1 file changed, 198 insertions(+)

diff --git a/trailer.c b/trailer.c
index db93a63..52108c2 100644
--- a/trailer.c
+++ b/trailer.c
@@ -47,3 +47,201 @@ static size_t alnum_len(const char *buf, size_t len)
len--;
return len;
 }
+
+static void free_trailer_item(struct trailer_item *item)
+{
+   free(item->conf.name);
+   free(item->conf.key);
+   free(item->conf.command);
+   free((char *)item->token);
+   free((char *)item->value);
+   free(item);
+}
+
+static void add_arg_to_input_list(struct trailer_item *in_tok,
+ struct trailer_item *arg_tok)
+{
+   if (arg_tok->conf.where == WHERE_AFTER) {
+   arg_tok->next = in_tok->next;
+   in_tok->next = arg_tok;
+   arg_tok->previous = in_tok;
+   if (arg_tok->next)
+   arg_tok->next->previous = arg_tok;
+   } else {
+   arg_tok->previous = in_tok->previous;
+   in_tok->previous = arg_tok;
+   arg_tok->next = in_tok;
+   if (arg_tok->previous)
+   arg_tok->previous->next = arg_tok;
+   }
+}
+
+static int check_if_different(struct trailer_item *in_tok,
+ struct trailer_item *arg_tok,
+ int alnum_len, int check_all)
+{
+   enum action_where where = arg_tok->conf.where;
+   do {
+   if (!in_tok)
+   return 1;
+   if (same_trailer(in_tok, arg_tok, alnum_len))
+   return 0;
+   /*
+* if we want to add a trailer after another one,
+* we have to check those before this one
+*/
+   in_tok = (where == WHERE_AFTER) ? in_tok->previous : 
in_tok->next;
+   } while (check_all);
+   return 1;
+}
+
+static void apply_arg_if_exists(struct trailer_item *in_tok,
+   struct trailer_item *arg_tok,
+   int alnum_len)
+{
+   switch (arg_tok->conf.if_exists) {
+   case EXISTS_DO_NOTHING:
+   free_trailer_item(arg_tok);
+   break;
+   case EXISTS_OVERWRITE:
+   free((char *)in_tok->value);
+   in_tok->value = xstrdup(arg_tok->value);
+   free_trailer_item(arg_tok);
+   break;
+   case EXISTS_ADD:
+   add_arg_to_input_list(in_tok, arg_tok);
+   break;
+   case EXISTS_ADD_IF_DIFFERENT:
+   if (check_if_different(in_tok, arg_tok, alnum_len, 1))
+   add_arg_to_input_list(in_tok, arg_tok);
+   else
+   free_trailer_item(arg_tok);
+   break;
+   case EXISTS_ADD_IF_DIFFERENT_NEIGHBOR:
+   if (check_if_different(in_tok, arg_tok, alnum_len, 0))
+   add_arg_to_input_list(in_tok, arg_tok);
+   else
+   free_trailer_item(arg_tok);
+   break;
+   }
+}
+
+static void remove_from_list(struct trailer_item *item,
+struct trailer_item **first)
+{
+   if (item->next)
+   item->next->previous = item->previous;
+   if (item->previous)
+   item->previous->next = item->next;
+   else
+   *first = item->next;
+}
+
+static struct trailer_item *remove_first(struct trailer_item **first)
+{
+   struct trailer_item *item = *first;
+   *first = item->next;
+   if (item->next) {
+   item->next->previous = NULL;
+   item->next = NULL;
+   }
+   return item;
+}
+
+static void process_input_token(struct trailer_item *in_tok,
+   struct trailer_item **arg_tok_first,
+   enum action_where where)
+{
+   struct trailer_item *arg_tok;
+   struct trailer_item *next_arg;
+
+   int after = where == WHERE_AFTER;
+   int tok_alnum_len = alnum_len(in_tok->token, strlen(in_tok->token));
+
+   for (arg_tok = *arg_tok_first; arg_tok; arg_tok = next_arg) {
+   next_arg = arg_tok->next;
+   if (!same_token(in_tok, arg_tok, tok_alnum_len))
+   continue;
+   if (arg_tok->conf.where != where)
+   continue;
+   remove_from_list(arg_tok, arg_tok_first);
+   apply_arg_if_exists(in_tok, arg_tok, tok_alnum_len);
+   /*
+ 

[PATCH v8 12/12] Documentation: add documentation for 'git interpret-trailers'

2014-03-26 Thread Christian Couder
Signed-off-by: Christian Couder 
---
 Documentation/git-interpret-trailers.txt | 123 +++
 1 file changed, 123 insertions(+)
 create mode 100644 Documentation/git-interpret-trailers.txt

diff --git a/Documentation/git-interpret-trailers.txt 
b/Documentation/git-interpret-trailers.txt
new file mode 100644
index 000..75ae386
--- /dev/null
+++ b/Documentation/git-interpret-trailers.txt
@@ -0,0 +1,123 @@
+git-interpret-trailers(1)
+=
+
+NAME
+
+git-interpret-trailers - help add stuctured information into commit messages
+
+SYNOPSIS
+
+[verse]
+'git interpret-trailers' [--trim-empty] [([(=|:)])...]
+
+DESCRIPTION
+---
+Help add RFC 822-like headers, called 'trailers', at the end of the
+otherwise free-form part of a commit message.
+
+This command is a filter. It reads the standard input for a commit
+message and applies the `token` arguments, if any, to this
+message. The resulting message is emited on the standard output.
+
+Some configuration variables control the way the `token` arguments are
+applied to the message and the way any existing trailer in the message
+is changed. They also make it possible to automatically add some
+trailers.
+
+By default, a 'token=value' or 'token:value' argument will be added
+only if no trailer with the same (token, value) pair is already in the
+message. The 'token' and 'value' parts will be trimmed to remove
+starting and trailing whitespace, and the resulting trimmed 'token'
+and 'value' will appear in the message like this:
+
+
+token: value
+
+
+By default, if there are already trailers with the same 'token', the
+new trailer will appear just after the last trailer with the same
+'token'. Otherwise it will appear at the end of the message.
+
+Note that 'trailers' do not follow and are not intended to follow many
+rules that are in RFC 822. For example they do not follow the line
+breaking rules, the encoding rules and probably many other rules.
+
+OPTIONS
+---
+--trim-empty::
+   If the 'value' part of any trailer contains only whitespace,
+   the whole trailer will be removed from the resulting message.
+
+CONFIGURATION VARIABLES
+---
+
+trailer..key::
+   This 'key' will be used instead of 'token' in the
+   trailer. After some alphanumeric characters, it can contain
+   some non alphanumeric characters like ':', '=' or '#' that will
+   be used instead of ':' to separate the token from the value in
+   the trailer, though the default ':' is more standard.
+
+trailer..where::
+   This can be either `after`, which is the default, or
+   `before`. If it is `before`, then a trailer with the specified
+   token, will appear before, instead of after, other trailers
+   with the same token, or otherwise at the beginning, instead of
+   at the end, of all the trailers.
+
+trailer..ifexist::
+   This option makes it possible to choose what action will be
+   performed when there is already at least one trailer with the
+   same token in the message.
++
+The valid values for this option are: `addIfDifferent` (this is the
+default), `addIfDifferentNeighbor`, `add`, `overwrite` or `doNothing`.
++
+With `addIfDifferent`, a new trailer will be added only if no trailer
+with the same (token, value) pair is already in the message.
++
+With `addIfDifferentNeighbor`, a new trailer will be added only if no
+trailer with the same (token, value) pair is above or below the line
+where the new trailer will be added.
++
+With `add`, a new trailer will be added, even if some trailers with
+the same (token, value) pair are already in the message.
++
+With `overwrite`, the new trailer will overwrite an existing trailer
+with the same token.
++
+With `doNothing`, nothing will be done, that is no new trailer will be
+added if there is already one with the same token in the message.
+
+trailer..ifmissing::
+   This option makes it possible to choose what action will be
+   performed when there is not yet any trailer with the same
+   token in the message.
++
+The valid values for this option are: `add` (this is the default) and
+`doNothing`.
++
+With `add`, a new trailer will be added.
++
+With `doNothing`, nothing will be done.
+
+trailer..command::
+   This option can be used to specify a shell command that will
+   be used to automatically add or modify a trailer with the
+   specified 'token'.
++
+When this option is specified, it is like if a special 'token=value'
+argument is added at the end of the command line, where 'value' will
+be given by the standard output of the specified command.
++
+If the command contains the `$ARG` string, this string will be
+replaced with the 'value' part of an existing trailer with the same
+token, if any, before the command is launched.
+
+SEE ALSO
+
+linkgit:git-commit[1]
+

[PATCH v8 11/12] trailer: add tests for commands in config file

2014-03-26 Thread Christian Couder
Signed-off-by: Christian Couder 
---
 t/t7513-interpret-trailers.sh | 71 +++
 1 file changed, 71 insertions(+)

diff --git a/t/t7513-interpret-trailers.sh b/t/t7513-interpret-trailers.sh
index 417a4f3..0a1f3b6 100755
--- a/t/t7513-interpret-trailers.sh
+++ b/t/t7513-interpret-trailers.sh
@@ -333,4 +333,75 @@ test_expect_success 'using "ifMissing = doNothing"' '
test_cmp expected actual
 '
 
+test_expect_success 'with simple command' '
+   git config trailer.sign.key "Signed-off-by: " &&
+   git config trailer.sign.where "after" &&
+   git config trailer.sign.ifExists "addIfDifferentNeighbor" &&
+   git config trailer.sign.command "echo \"A U Thor 
\"" &&
+   cat complex_message_body >expected &&
+   sed -e "s/ Z\$/ /" >>expected <<-\EOF &&
+   Fixes: Z
+   Acked-by= Z
+   Reviewed-by: Z
+   Signed-off-by: Z
+   Signed-off-by: A U Thor 
+   EOF
+   git interpret-trailers "review:" "fix=22" actual &&
+   test_cmp expected actual
+'
+
+test_expect_success 'with command using commiter information' '
+   git config trailer.sign.ifExists "addIfDifferent" &&
+   git config trailer.sign.command "echo \"\$GIT_COMMITTER_NAME 
<\$GIT_COMMITTER_EMAIL>\"" &&
+   cat complex_message_body >expected &&
+   sed -e "s/ Z\$/ /" >>expected <<-\EOF &&
+   Fixes: Z
+   Acked-by= Z
+   Reviewed-by: Z
+   Signed-off-by: Z
+   Signed-off-by: C O Mitter 
+   EOF
+   git interpret-trailers "review:" "fix=22" actual &&
+   test_cmp expected actual
+'
+
+test_expect_success 'with command using author information' '
+   git config trailer.sign.key "Signed-off-by: " &&
+   git config trailer.sign.where "after" &&
+   git config trailer.sign.ifExists "addIfDifferentNeighbor" &&
+   git config trailer.sign.command "echo \"\$GIT_AUTHOR_NAME 
<\$GIT_AUTHOR_EMAIL>\"" &&
+   cat complex_message_body >expected &&
+   sed -e "s/ Z\$/ /" >>expected <<-\EOF &&
+   Fixes: Z
+   Acked-by= Z
+   Reviewed-by: Z
+   Signed-off-by: Z
+   Signed-off-by: A U Thor 
+   EOF
+   git interpret-trailers "review:" "fix=22" actual &&
+   test_cmp expected actual
+'
+
+test_expect_success 'setup a commit' '
+   echo "Content of the first commit." > a.txt &&
+   git add a.txt &&
+   git commit -m "Add file a.txt"
+'
+
+test_expect_success 'with command using $ARG' '
+   git config trailer.fix.ifExists "overwrite" &&
+   git config trailer.fix.command "git log -1 --oneline --format=\"%h 
(%s)\" --abbrev-commit --abbrev=14 \$ARG" &&
+   FIXED=$(git log -1 --oneline --format="%h (%s)" --abbrev-commit 
--abbrev=14 HEAD) &&
+   cat complex_message_body >expected &&
+   sed -e "s/ Z\$/ /" >>expected <<-EOF &&
+   Fixes: $FIXED
+   Acked-by= Z
+   Reviewed-by: Z
+   Signed-off-by: Z
+   Signed-off-by: A U Thor 
+   EOF
+   git interpret-trailers "review:" "fix=HEAD" actual &&
+   test_cmp expected actual
+'
+
 test_done
-- 
1.9.0.164.g3aa33cd.dirty


--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v8 05/12] trailer: process command line trailer arguments

2014-03-26 Thread Christian Couder
Parse the trailer command line arguments and put
the result into an arg_tok doubly linked list.

Signed-off-by: Christian Couder 
---
 trailer.c | 103 ++
 1 file changed, 103 insertions(+)

diff --git a/trailer.c b/trailer.c
index b5a0943..1871843 100644
--- a/trailer.c
+++ b/trailer.c
@@ -398,3 +398,106 @@ static int git_trailer_config(const char *conf_key, const 
char *value, void *cb)
}
return 0;
 }
+
+static int parse_trailer(struct strbuf *tok, struct strbuf *val, const char 
*trailer)
+{
+   size_t len = strcspn(trailer, "=:");
+   if (len == 0)
+   return error(_("empty trailer token in trailer '%s'"), trailer);
+   if (len < strlen(trailer)) {
+   strbuf_add(tok, trailer, len);
+   strbuf_trim(tok);
+   strbuf_addstr(val, trailer + len + 1);
+   strbuf_trim(val);
+   } else {
+   strbuf_addstr(tok, trailer);
+   strbuf_trim(tok);
+   }
+   return 0;
+}
+
+
+static void duplicate_conf(struct conf_info *dst, struct conf_info *src)
+{
+   *dst = *src;
+   if (src->name)
+   dst->name = xstrdup(src->name);
+   if (src->key)
+   dst->key = xstrdup(src->key);
+   if (src->command)
+   dst->command = xstrdup(src->command);
+}
+
+static struct trailer_item *new_trailer_item(struct trailer_item *conf_item,
+char *tok, char *val)
+{
+   struct trailer_item *new = xcalloc(sizeof(*new), 1);
+   new->value = val;
+
+   if (conf_item) {
+   duplicate_conf(&new->conf, &conf_item->conf);
+   new->token = xstrdup(conf_item->conf.key);
+   free(tok);
+   } else
+   new->token = tok;
+
+   return new;
+}
+
+static struct trailer_item *create_trailer_item(const char *string)
+{
+   struct strbuf tok = STRBUF_INIT;
+   struct strbuf val = STRBUF_INIT;
+   struct trailer_item *item;
+   int tok_alnum_len;
+
+   if (parse_trailer(&tok, &val, string))
+   return NULL;
+
+   tok_alnum_len = alnum_len(tok.buf, tok.len);
+
+   /* Lookup if the token matches something in the config */
+   for (item = first_conf_item; item; item = item->next) {
+   if (!strncasecmp(tok.buf, item->conf.key, tok_alnum_len) ||
+   !strncasecmp(tok.buf, item->conf.name, tok_alnum_len)) {
+   strbuf_release(&tok);
+   return new_trailer_item(item,
+   NULL,
+   strbuf_detach(&val, NULL));
+   }
+   }
+
+   return new_trailer_item(NULL,
+   strbuf_detach(&tok, NULL),
+   strbuf_detach(&val, NULL));
+}
+
+static void add_trailer_item(struct trailer_item **first,
+struct trailer_item **last,
+struct trailer_item *new)
+{
+   if (!new)
+   return;
+   if (!*last) {
+   *first = new;
+   *last = new;
+   } else {
+   (*last)->next = new;
+   new->previous = *last;
+   *last = new;
+   }
+}
+
+static struct trailer_item *process_command_line_args(int argc, const char 
**argv)
+{
+   int i;
+   struct trailer_item *arg_tok_first = NULL;
+   struct trailer_item *arg_tok_last = NULL;
+
+   for (i = 0; i < argc; i++) {
+   struct trailer_item *new = create_trailer_item(argv[i]);
+   add_trailer_item(&arg_tok_first, &arg_tok_last, new);
+   }
+
+   return arg_tok_first;
+}
-- 
1.9.0.164.g3aa33cd.dirty


--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v8 01/12] Add data structures and basic functions for commit trailers

2014-03-26 Thread Christian Couder
We will use a doubly linked list to store all information
about trailers and their configuration.

This way we can easily remove or add trailers to or from
trailer lists while traversing the lists in either direction.

Signed-off-by: Christian Couder 
---
 Makefile  |  1 +
 trailer.c | 49 +
 2 files changed, 50 insertions(+)
 create mode 100644 trailer.c

diff --git a/Makefile b/Makefile
index d4ce53a..ec67ae1 100644
--- a/Makefile
+++ b/Makefile
@@ -883,6 +883,7 @@ LIB_OBJS += submodule.o
 LIB_OBJS += symlinks.o
 LIB_OBJS += tag.o
 LIB_OBJS += trace.o
+LIB_OBJS += trailer.o
 LIB_OBJS += transport.o
 LIB_OBJS += transport-helper.o
 LIB_OBJS += tree-diff.o
diff --git a/trailer.c b/trailer.c
new file mode 100644
index 000..db93a63
--- /dev/null
+++ b/trailer.c
@@ -0,0 +1,49 @@
+#include "cache.h"
+/*
+ * Copyright (c) 2013, 2014 Christian Couder 
+ */
+
+enum action_where { WHERE_AFTER, WHERE_BEFORE };
+enum action_if_exists { EXISTS_ADD_IF_DIFFERENT, 
EXISTS_ADD_IF_DIFFERENT_NEIGHBOR,
+   EXISTS_ADD, EXISTS_OVERWRITE, EXISTS_DO_NOTHING };
+enum action_if_missing { MISSING_ADD, MISSING_DO_NOTHING };
+
+struct conf_info {
+   char *name;
+   char *key;
+   char *command;
+   enum action_where where;
+   enum action_if_exists if_exists;
+   enum action_if_missing if_missing;
+};
+
+struct trailer_item {
+   struct trailer_item *previous;
+   struct trailer_item *next;
+   const char *token;
+   const char *value;
+   struct conf_info conf;
+};
+
+static int same_token(struct trailer_item *a, struct trailer_item *b, int 
alnum_len)
+{
+   return !strncasecmp(a->token, b->token, alnum_len);
+}
+
+static int same_value(struct trailer_item *a, struct trailer_item *b)
+{
+   return !strcasecmp(a->value, b->value);
+}
+
+static int same_trailer(struct trailer_item *a, struct trailer_item *b, int 
alnum_len)
+{
+   return same_token(a, b, alnum_len) && same_value(a, b);
+}
+
+/* Get the length of buf from its beginning until its last alphanumeric 
character */
+static size_t alnum_len(const char *buf, size_t len)
+{
+   while (len > 0 && !isalnum(buf[len - 1]))
+   len--;
+   return len;
+}
-- 
1.9.0.164.g3aa33cd.dirty


--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v8 08/12] trailer: add interpret-trailers command

2014-03-26 Thread Christian Couder
This patch adds the "git interpret-trailers" command.
This command uses the previously added process_trailers()
function in trailer.c.

Signed-off-by: Christian Couder 
---
 .gitignore   |  1 +
 Makefile |  1 +
 builtin.h|  1 +
 builtin/interpret-trailers.c | 33 +
 git.c|  1 +
 5 files changed, 37 insertions(+)
 create mode 100644 builtin/interpret-trailers.c

diff --git a/.gitignore b/.gitignore
index dc600f9..c2a0b19 100644
--- a/.gitignore
+++ b/.gitignore
@@ -74,6 +74,7 @@
 /git-index-pack
 /git-init
 /git-init-db
+/git-interpret-trailers
 /git-instaweb
 /git-log
 /git-ls-files
diff --git a/Makefile b/Makefile
index ec67ae1..94f7e95 100644
--- a/Makefile
+++ b/Makefile
@@ -947,6 +947,7 @@ BUILTIN_OBJS += builtin/hash-object.o
 BUILTIN_OBJS += builtin/help.o
 BUILTIN_OBJS += builtin/index-pack.o
 BUILTIN_OBJS += builtin/init-db.o
+BUILTIN_OBJS += builtin/interpret-trailers.o
 BUILTIN_OBJS += builtin/log.o
 BUILTIN_OBJS += builtin/ls-files.o
 BUILTIN_OBJS += builtin/ls-remote.o
diff --git a/builtin.h b/builtin.h
index c47c110..8ca0065 100644
--- a/builtin.h
+++ b/builtin.h
@@ -73,6 +73,7 @@ extern int cmd_hash_object(int argc, const char **argv, const 
char *prefix);
 extern int cmd_help(int argc, const char **argv, const char *prefix);
 extern int cmd_index_pack(int argc, const char **argv, const char *prefix);
 extern int cmd_init_db(int argc, const char **argv, const char *prefix);
+extern int cmd_interpret_trailers(int argc, const char **argv, const char 
*prefix);
 extern int cmd_log(int argc, const char **argv, const char *prefix);
 extern int cmd_log_reflog(int argc, const char **argv, const char *prefix);
 extern int cmd_ls_files(int argc, const char **argv, const char *prefix);
diff --git a/builtin/interpret-trailers.c b/builtin/interpret-trailers.c
new file mode 100644
index 000..0c8ca72
--- /dev/null
+++ b/builtin/interpret-trailers.c
@@ -0,0 +1,33 @@
+/*
+ * Builtin "git interpret-trailers"
+ *
+ * Copyright (c) 2013, 2014 Christian Couder 
+ *
+ */
+
+#include "cache.h"
+#include "builtin.h"
+#include "parse-options.h"
+#include "trailer.h"
+
+static const char * const git_interpret_trailers_usage[] = {
+   N_("git interpret-trailers [--trim-empty] 
[([(=|:)])...]"),
+   NULL
+};
+
+int cmd_interpret_trailers(int argc, const char **argv, const char *prefix)
+{
+   int trim_empty = 0;
+
+   struct option options[] = {
+   OPT_BOOL(0, "trim-empty", &trim_empty, N_("trim empty 
trailers")),
+   OPT_END()
+   };
+
+   argc = parse_options(argc, argv, prefix, options,
+git_interpret_trailers_usage, 0);
+
+   process_trailers(trim_empty, argc, argv);
+
+   return 0;
+}
diff --git a/git.c b/git.c
index 7cf2953..63a03eb 100644
--- a/git.c
+++ b/git.c
@@ -380,6 +380,7 @@ static struct cmd_struct commands[] = {
{ "index-pack", cmd_index_pack, RUN_SETUP_GENTLY },
{ "init", cmd_init_db },
{ "init-db", cmd_init_db },
+   { "interpret-trailers", cmd_interpret_trailers, RUN_SETUP },
{ "log", cmd_log, RUN_SETUP },
{ "ls-files", cmd_ls_files, RUN_SETUP },
{ "ls-remote", cmd_ls_remote, RUN_SETUP_GENTLY },
-- 
1.9.0.164.g3aa33cd.dirty


--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v8 09/12] trailer: add tests for "git interpret-trailers"

2014-03-26 Thread Christian Couder
Signed-off-by: Christian Couder 
---
 t/t7513-interpret-trailers.sh | 336 ++
 1 file changed, 336 insertions(+)
 create mode 100755 t/t7513-interpret-trailers.sh

diff --git a/t/t7513-interpret-trailers.sh b/t/t7513-interpret-trailers.sh
new file mode 100755
index 000..417a4f3
--- /dev/null
+++ b/t/t7513-interpret-trailers.sh
@@ -0,0 +1,336 @@
+#!/bin/sh
+#
+# Copyright (c) 2013 Christian Couder
+#
+
+test_description='git interpret-trailers'
+
+. ./test-lib.sh
+
+# When we want one trailing space at the end of each line, let's use sed
+# to make sure that these spaces are not removed by any automatic tool.
+
+test_expect_success 'setup' '
+   cat >basic_message <<-\EOF &&
+   subject
+
+   body
+   EOF
+   cat >complex_message_body <<-\EOF &&
+   my subject
+
+   my body which is long
+   and contains some special
+   chars like : = ? !
+
+   EOF
+   sed -e "s/ Z\$/ /" >complex_message_trailers <<-\EOF
+   Fixes: Z
+   Acked-by: Z
+   Reviewed-by: Z
+   Signed-off-by: Z
+   EOF
+'
+
+test_expect_success 'without config' '
+   sed -e "s/ Z\$/ /" >expected <<-\EOF &&
+   ack: Peff
+   Reviewed-by: Z
+   Acked-by: Johan
+   EOF
+   git interpret-trailers "ack = Peff" "Reviewed-by" "Acked-by: Johan" 
>actual &&
+   test_cmp expected actual
+'
+
+test_expect_success '--trim-empty without config' '
+   cat >expected <<-\EOF &&
+   ack: Peff
+   Acked-by: Johan
+   EOF
+   git interpret-trailers --trim-empty "ack = Peff" "Reviewed-by" 
"Acked-by: Johan" "sob:" >actual &&
+   test_cmp expected actual
+'
+
+test_expect_success 'with config setup' '
+   git config trailer.ack.key "Acked-by: " &&
+   cat >expected <<-\EOF &&
+   Acked-by: Peff
+   EOF
+   git interpret-trailers --trim-empty "ack = Peff" >actual &&
+   test_cmp expected actual &&
+   git interpret-trailers --trim-empty "Acked-by = Peff" >actual &&
+   test_cmp expected actual &&
+   git interpret-trailers --trim-empty "Acked-by :Peff" >actual &&
+   test_cmp expected actual
+'
+
+test_expect_success 'with config setup and = sign' '
+   git config trailer.ack.key "Acked-by= " &&
+   cat >expected <<-\EOF &&
+   Acked-by= Peff
+   EOF
+   git interpret-trailers --trim-empty "ack = Peff" >actual &&
+   test_cmp expected actual &&
+   git interpret-trailers --trim-empty "Acked-by= Peff" >actual &&
+   test_cmp expected actual &&
+   git interpret-trailers --trim-empty "Acked-by : Peff" >actual &&
+   test_cmp expected actual
+'
+
+test_expect_success 'with config setup and # sign' '
+   git config trailer.bug.key "Bug #" &&
+   cat >expected <<-\EOF &&
+   Bug #42
+   EOF
+   git interpret-trailers --trim-empty "bug = 42" >actual &&
+   test_cmp expected actual
+'
+
+test_expect_success 'with commit basic message' '
+   git interpret-trailers actual &&
+   test_cmp basic_message actual
+'
+
+test_expect_success 'with commit complex message' '
+   cat complex_message_body complex_message_trailers >complex_message &&
+   cat complex_message_body >expected &&
+   sed -e "s/ Z\$/ /" >>expected <<-\EOF &&
+   Fixes: Z
+   Acked-by= Z
+   Reviewed-by: Z
+   Signed-off-by: Z
+   EOF
+   git interpret-trailers actual &&
+   test_cmp expected actual
+'
+
+test_expect_success 'with commit complex message and args' '
+   cat complex_message_body >expected &&
+   sed -e "s/ Z\$/ /" >>expected <<-\EOF &&
+   Fixes: Z
+   Acked-by= Z
+   Acked-by= Peff
+   Reviewed-by: Z
+   Signed-off-by: Z
+   Bug #42
+   EOF
+   git interpret-trailers "ack: Peff" "bug: 42" actual &&
+   test_cmp expected actual
+'
+
+test_expect_success 'with commit complex message, args and --trim-empty' '
+   cat complex_message_body >expected &&
+   cat >>expected <<-\EOF &&
+   Acked-by= Peff
+   Bug #42
+   EOF
+   git interpret-trailers --trim-empty "ack: Peff" "bug: 42" 
actual &&
+   test_cmp expected actual
+'
+
+test_expect_success 'using "where = before"' '
+   git config trailer.bug.where "before" &&
+   cat complex_message_body >expected &&
+   sed -e "s/ Z\$/ /" >>expected <<-\EOF &&
+   Bug #42
+   Fixes: Z
+   Acked-by= Z
+   Acked-by= Peff
+   Reviewed-by: Z
+   Signed-off-by: Z
+   EOF
+   git interpret-trailers "ack: Peff" "bug: 42" actual &&
+   test_cmp expected actual
+'
+
+test_expect_success 'using "where = before" for a token in the middle of the 
message' '
+   g

Re: [PATCH/RFC 0/6] reuse deltas found by bitmaps

2014-03-26 Thread Junio C Hamano
Jeff King  writes:

> Just looking at the 128-day case again, using bitmaps increased our
> server CPU time _and_ made a much bigger pack. This series not only
> fixes the CPU time regression, but it also drops the server CPU time to
> almost nothing. That's a nice improvement, and it makes perfect sense:
> we are reusing on-disk deltas instead of on-the-fly computing deltas
> against the preferred bases.

True.

> I think we could still add the objects from the tip of the client's HAVE
> list.

That should make the result at least per to the non-bitmap case,
right?

> This patch would still be a CPU win on top of that, because it
> would reduce the number of objects which need a delta search in the
> first place.

Yes.

> So I think the next steps are probably:
>
>   1. Measure the "all objects are preferred bases" approach and confirm
>  that it is bad.

;-)

>   2. Measure the "reused deltas become preferred bases" approach. I
>  expect the resulting size to be slightly better than what I have
>  now, but not as good as v1.9.0's size (but taking less CPU time).

Do you mean "the bases for reused deltas become preferred bases, so
that we can deltify more objects off of them"?

>   3. Measure the "figure out boundaries and add them as preferred bases,
>  like we do without bitmaps" approach. I expect this to behave
>  similarly to v1.9.0.

Yes.

>   4. Combine (2) and (3) and measure them. I'm _hoping_ this will give
>  us the best of both worlds, but I still want to do the individual
>  measurements so we can see where any improvement is coming from.

Sensible.  Thanks.
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 1/6] t/perf-lib: factor boilerplate out of test_perf

2014-03-26 Thread Junio C Hamano
Jeff King  writes:

> About half of test_perf() is boilerplate, and half is
> actually related to running the perf test. Let's split it
> into two functions, so that we can reuse the boilerplate in
> future commits.
>
> Signed-off-by: Jeff King 
> ---
>  t/perf/perf-lib.sh | 61 
> +++---
>  1 file changed, 35 insertions(+), 26 deletions(-)

These early steps somewhat conflict with another topic that is
stalled (due to having no real users) on 'pu'.  I do not think we
would terribly mind dropping tg/perf-lib-test-perf-cleanup and have
it rebased if the author or somebody else wants to have it in my
tree later, but just FYI.

>
> diff --git a/t/perf/perf-lib.sh b/t/perf/perf-lib.sh
> index a8c9574..20f306a 100644
> --- a/t/perf/perf-lib.sh
> +++ b/t/perf/perf-lib.sh
> @@ -150,8 +150,8 @@ exit $ret' >&3 2>&4
>   return "$eval_ret"
>  }
>  
> -
> -test_perf () {
> +test_wrapper_ () {
> + test_wrapper_func_=$1; shift
>   test_start_
>   test "$#" = 3 && { test_prereq=$1; shift; } || test_prereq=
>   test "$#" = 2 ||
> @@ -162,35 +162,44 @@ test_perf () {
>   base=$(basename "$0" .sh)
>   echo "$test_count" >>"$perf_results_dir"/$base.subtests
>   echo "$1" >"$perf_results_dir"/$base.$test_count.descr
> - if test -z "$verbose"; then
> - printf "%s" "perf $test_count - $1:"
> - else
> - echo "perf $test_count - $1:"
> - fi
> - for i in $(test_seq 1 $GIT_PERF_REPEAT_COUNT); do
> - say >&3 "running: $2"
> - if test_run_perf_ "$2"
> - then
> - if test -z "$verbose"; then
> - printf " %s" "$i"
> - else
> - echo "* timing run 
> $i/$GIT_PERF_REPEAT_COUNT:"
> - fi
> + base="$perf_results_dir"/"$perf_results_prefix$(basename "$0" 
> .sh)"."$test_count"
> + "$test_wrapper_func_" "$@"
> + fi
> +
> + test_finish_
> +}
> +
> +test_perf_ () {
> + if test -z "$verbose"; then
> + printf "%s" "perf $test_count - $1:"
> + else
> + echo "perf $test_count - $1:"
> + fi
> + for i in $(test_seq 1 $GIT_PERF_REPEAT_COUNT); do
> + say >&3 "running: $2"
> + if test_run_perf_ "$2"
> + then
> + if test -z "$verbose"; then
> + printf " %s" "$i"
>   else
> - test -z "$verbose" && echo
> - test_failure_ "$@"
> - break
> + echo "* timing run $i/$GIT_PERF_REPEAT_COUNT:"
>   fi
> - done
> - if test -z "$verbose"; then
> - echo " ok"
>   else
> - test_ok_ "$1"
> + test -z "$verbose" && echo
> + test_failure_ "$@"
> + break
>   fi
> - base="$perf_results_dir"/"$perf_results_prefix$(basename "$0" 
> .sh)"."$test_count"
> - "$TEST_DIRECTORY"/perf/min_time.perl test_time.* >"$base".times
> + done
> + if test -z "$verbose"; then
> + echo " ok"
> + else
> + test_ok_ "$1"
>   fi
> - test_finish_
> + "$TEST_DIRECTORY"/perf/min_time.perl test_time.* >"$base".times
> +}
> +
> +test_perf () {
> + test_wrapper_ test_perf_ "$@"
>  }
>  
>  # We extend test_done to print timings at the end (./run disables this
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH/RFC 0/6] reuse deltas found by bitmaps

2014-03-26 Thread Jeff King
On Wed, Mar 26, 2014 at 03:31:41PM -0700, Junio C Hamano wrote:

> > I think we could still add the objects from the tip of the client's HAVE
> > list.
> 
> That should make the result at least per to the non-bitmap case,
> right?

That's my expectation.
> 
> >   2. Measure the "reused deltas become preferred bases" approach. I
> >  expect the resulting size to be slightly better than what I have
> >  now, but not as good as v1.9.0's size (but taking less CPU time).
> 
> Do you mean "the bases for reused deltas become preferred bases, so
> that we can deltify more objects off of them"?

Exactly.

I'll update more when I have results for some of these. :)

-Peff
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH/RFC 0/6] reuse deltas found by bitmaps

2014-03-26 Thread Siddharth Agarwal

On 03/26/2014 12:22 AM, Jeff King wrote:

[tl;dr the patch is the same as before, but there is a script to measure
its effects; please try it out on your repos]


Here are results from one of our repos:

Test origin HEAD
-
5311.3: server   (1 days)1.77(2.49+0.15) 0.76(0.65+0.12) -57.1%
5311.4: size (1 days)   7.8M3.1M -60.2%
5311.5: client   (1 days)0.56(0.48+0.03) 1.18(0.97+0.05) +110.7%
5311.7: server   (2 days)2.79(3.68+0.25) 0.77(0.65+0.14) -72.4%
5311.8: size (2 days)  24.2M6.8M -71.8%
5311.9: client   (2 days)1.14(0.95+0.10) 2.72(2.33+0.13) +138.6%
5311.11: server   (4 days)   3.70(4.76+0.28) 0.84(0.72+0.14) -77.3%
5311.12: size (4 days) 51.2M   18.9M -63.0%
5311.13: client   (4 days)   2.29(2.02+0.29) 4.58(3.91+0.30) +100.0%
5311.15: server   (8 days)   5.16(7.48+0.38) 1.20(1.18+0.21) -76.7%
5311.16: size (8 days) 78.3M   42.6M -45.5%
5311.17: client   (8 days)   3.73(3.67+0.40) 6.59(5.95+0.51) +76.7%
5311.19: server  (16 days)   6.48(10.27+0.52)1.60(1.85+0.27) -75.3%
5311.20: size(16 days) 97.5M   64.0M -34.4%
5311.21: client  (16 days)   5.31(5.76+0.57) 8.99(8.61+0.68) +69.3%
5311.23: server  (32 days)   8.56(14.00+0.67)2.31(2.91+0.37) -73.0%
5311.24: size(32 days)124.7M   92.0M -26.2%
5311.25: client  (32 days)   7.69(9.20+0.76) 12.80(13.07+0.91) +66.4%
5311.27: server  (64 days)   37.47(45.48+1.55)   29.75(29.58+0.96) -20.6%
5311.28: size(64 days)245.5M  207.1M -15.6%
5311.29: client  (64 days)   15.11(18.26+1.58)   25.02(25.90+2.03) +65.6%
5311.31: server (128 days)   43.85(57.02+2.57)   29.88(29.54+1.35) -31.9%
5311.32: size   (128 days)507.3M  461.6M -9.0%
5311.33: client (128 days)   27.13(31.54+3.32)   37.76(39.49+3.16) +39.2%

I'm currently running tests on a much larger repo than that. The full 
perf run will take several hours on that, so the soonest I can likely 
publish results for that is tomorrow.

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] t4212: handle systems with post-apocalyptic gmtime

2014-03-26 Thread Charles Bailey
On Wed, Mar 26, 2014 at 05:57:41PM -0400, Jeff King wrote:
> Hmm, so the year you got is actually: 1623969404. That still seems off
> to me by a factor 20. I don't know if this is really worth digging into
> that much further, but I wonder what you would get for timestamps of:
> 
>   9
>   
>   999
>   etc.
> 

AIX goes negative at about the same time Linux and Solaris segfault:

999 Sun Apr 26 10:46:39 1970 -0700
 Sat Mar 3 02:46:39 1973 -0700
9 Sat Sep 8 18:46:39 2001 -0700
99 Sat Nov 20 10:46:39 2286 -0700
999 Wed Nov 16 02:46:39 5138 -0700
 Thu Sep 26 18:46:39 33658 -0700
9 Sun May 20 10:46:39 318857 -0700
99 Sat Nov 7 02:46:39 3170843 -0700
999 Sat Jul 4 18:46:39 31690708 -0700
 Sat Jan 25 10:46:39 316889355 -0700
9 Wed Sep 6 02:46:39 -1126091476 -0700
99 Thu Oct 24 18:46:39 1623969404 -0700

So, very bogus values.

Charles.
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v8 01/12] Add data structures and basic functions for commit trailers

2014-03-26 Thread Junio C Hamano
Christian Couder  writes:

>> Subject: Re: [PATCH v8 01/12] Add data structures and basic functions for 
>> commit trailers

As pointed out many times for GSoC microprojects students, limit the
scope with "area:" prefix for the commit title, e.g.

Subject: trailers: add data structures and basic functions

Please also refer to what has already been queued on 'pu' to avoid
wasting review bandwidth and mark patches that are unchanged as such
(but do send them to the list for review, so that people who haven't
seen the previous round can also comment).

As far as I can tell, this is the same as 8d1c70e5 (trailers: add
data structures and basic functions, 2014-03-06), so I'll queue the
remainder on top of that commit already on 'pu', which incidentally
will preserve the original author timestamp from the previous
incarnation.

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v8 00/12] Add interpret-trailers builtin

2014-03-26 Thread Junio C Hamano
Christian Couder  writes:

> Until now git commit has only supported the well known
> "Signed-off-by: " trailer, that is used by many projects like
> the Linux kernel and Git.
>
> It is better to implement features for these trailers first in a
> new command rather than in builtin/commit.c, because this way the
> prepare-commit-msg and commit-msg hooks can reuse this command.

The "first" is somewhat questionable.

It is better to keep builtin/commit.c uncontaminated by any more
hard-wired logic, like what we have for the signed-off-by line.  Any
new things can and should be doable in hooks, and this filter would
help writing these hooks.

And that is why the design goal of the filter is to make it at least
as powerful as the built-in logic we have for signed-off-by lines;
that would allow us to later eject the hard-wired logic for
signed-off-by line from the main codepath, if/when we wanted to.

Alternatively, we could build a library-ish API around this filter
code and replace the hard-wired logic for signed-off-by line with a
call into that API, if/when we wanted to, but that requires (in
addition to the "at least as powerful as the built-in logic") that
the implementation of this stand-alone filter can be cleanly made
into a reusable library, so that is a bit higher bar to cross than
"everything can be doable with hooks" alternative.

> 3) Changes since version 7, thanks to Junio:
>
> * improved handling of empty trailer token
> * clearer way to create 'expected' files in tests
> * other small test cleanups
> * improved commit message
> * new way to parse config keys
> * strcasecmp() is not used anymore in some config related functions

It is unclear which of the 12 patches are unchanged since the last
round.  Are reviewers expected to re-read all of them?

> Some values from the config file are lowercased instead.
> To enable that a new patch (3/12) is introduced to rationalize
> lowercase related functions. I am not very happy with these
> changes.

I can see why you are not very happy.  Perhaps it may make you
happier if you did not move lowercase() at all, did the
xstrdup_tolower() in a cleaner and more efficient way, and only used
the latter in the code?

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v8 03/12] Move lower case functions into wrapper.c

2014-03-26 Thread Junio C Hamano
Christian Couder  writes:

> diff --git a/wrapper.c b/wrapper.c
> index 0cc5636..c46026a 100644
> --- a/wrapper.c
> +++ b/wrapper.c
> @@ -455,3 +455,17 @@ struct passwd *xgetpwuid_self(void)
>   errno ? strerror(errno) : _("no such user"));
>   return pw;
>  }
> +
> +void lowercase(char *p)
> +{
> + for (; *p; p++)
> + *p = tolower(*p);
> +}
> +
> +char *xstrdup_tolower(const char *str)
> +{
> + char *dup = xstrdup(str);
> + lowercase(dup);
> + return dup;
> +}
> +

As a pure code-movement step, this may be OK, but I am not sure if
both of them want to be public functions in this shape.

Perhaps

char *downcase_copy(const char *str)
{
char *copy = xmalloc(strlen(str) + 1);
int i;
for (i = 0; str[i]; i++)
copy[i] = tolower(str[i]);
copy[i] = '\0';
return copy;
}

may avoid having to copy things twice.  Do you need the other
function exposed?

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v2 06/17] ls-files: add --color to highlight file names

2014-03-26 Thread Duy Nguyen
On Thu, Mar 27, 2014 at 2:13 AM, Eric Sunshine  wrote:
> On Wed, Mar 26, 2014 at 9:48 AM, Nguyễn Thái Ngọc Duy  
> wrote:
>> Signed-off-by: Nguyễn Thái Ngọc Duy 
>> ---
>>  Documentation/git-ls-files.txt |  9 +
>>  builtin/ls-files.c | 38 +++---
>>  2 files changed, 44 insertions(+), 3 deletions(-)
>>
>> diff --git a/Documentation/git-ls-files.txt b/Documentation/git-ls-files.txt
>> index c0856a6..5c1b7f3 100644
>> --- a/Documentation/git-ls-files.txt
>> +++ b/Documentation/git-ls-files.txt
>> @@ -147,6 +147,15 @@ a space) at the start of each line:
>> possible for manual inspection; the exact format may change at
>> any time.
>>
>> +--color[=]::
>> +   Color file names. The value must be always (default), never,
>> +   or auto.
>
> Here, the default is "always"...

These (.txt changes in other patches as well) are mostly copy and
paste from existing .txt files. You may want to grep through and fix
other places as well, in a separate series.

>
>> +--no-color::
>> +   Turn off coloring, even when the configuration file gives the
>> +   default to color output, same as `--color=never`. This is the
>> +   default.
>
> But, here the default is "never".

What I mean is color is turned off by default for ls-files (in
contrast, ls has color on by default). The default 'always' means that
if you write --color without the  part, then it's
--color=always. How do I phrase to make it clear?
-- 
Duy
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v2 05/17] ls-files: buffer full item in strbuf before printing

2014-03-26 Thread Duy Nguyen
On Thu, Mar 27, 2014 at 2:22 AM, Eric Sunshine  wrote:
>>  static void show_dir_entry(const char *tag, struct dir_entry *ent)
>>  {
>> +   static struct strbuf sb = STRBUF_INIT;
>> int len = max_prefix_len;
>>
>> if (len >= ent->len)
>> @@ -67,8 +79,10 @@ static void show_dir_entry(const char *tag, struct 
>> dir_entry *ent)
>> if (!dir_path_match(ent, &pathspec, len, ps_matched))
>> return;
>>
>> -   fputs(tag, stdout);
>> -   write_name(ent->name);
>> +   strbuf_reset(&sb);
>> +   strbuf_addstr(&sb, tag);
>> +   write_name(&sb, ent->name);
>> +   strbuf_fputs(&sb, stdout);
>
> strbuf_release(&sb);

Not strictly necessary because sb is static and will be reset at the
next call. I just want to lower the number of allocation (write_name
allocates some more). It may be a premature optimization though.

The same for changes in show_ce_entry().
-- 
Duy
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v3] Clarify pre-push hook documentation

2014-03-26 Thread Philip Oakley

From: "Junio C Hamano" 

David Cowden  writes:


The documentation as-is does not mention that the pre-push hook is
executed even when there is nothing to push.  This can lead a new
reader to believe there will always be lines fed to the script's
standard input and cause minor confusion as to what is happening
when there are no lines provided to the pre-push script.

Signed-off-by: David Cowden 
---

Notes:
I'm not sure if I've covered every case here.  If there are more
cases to
consider, please let me know and I can update to include them.


I do not think of any offhand, but a more important point that I was
trying to get at was that we should not give an incorrect impression
to the readers that the scenario that is described is the only case
they need to be worried about by pretending to be exhaustive.

The "may" in your wording "This may happen when" may be good enough
to hint that these may not be the only cases.


c.f.
http://stackoverflow.com/questions/22585091/git-hooks-pre-push-script-does-not-receive-input-via-stdin

 Documentation/githooks.txt | 9 +
 1 file changed, 9 insertions(+)

diff --git a/Documentation/githooks.txt b/Documentation/githooks.txt
index d954bf6..1fd6da9 100644
--- a/Documentation/githooks.txt
+++ b/Documentation/githooks.txt
@@ -203,6 +203,15 @@ SHA-1>` will be 40 `0`.  If the local commit was
specified by something other
 than a name which could be expanded (such as `HEAD~`, or a SHA-1) it
will be
 supplied as it was originally given.

+The hook is executed regardless of whether changes will actually be
pushed or
+not.  This may happen when 'git push' is called and:
+
+ - the remote ref is already up to date, or
+ - pushing to the remote ref cannot be handled by a simple
fast-forward
+
+In other words, the script is called for every push.  In the event
that nothing
+is to be pushed, no data will be provided on the script's standard
input.


Doesn't an 'in other words' indicate it could be further tightened?
Maybe
   "If there is nothing to push, the hook will still run, but the input
   line will be empty.

   Likewise the hook will still run for other cases such as:
   - the remote ref is already up to date,
   - pushing to the remote ref cannot be handled by a simple
 fast-forward,
   - etc."



When two things are to be pushed, the script will see the two
things.  When one thing is to be pushed, the script will see the one
thing.  When no thing is to be pushed, the script will see no thing
on its standard input.

But isn't that obvious?  I still wonder if we really need to single
out that "nothing" case.  The more important thing is that it is
invoked even in the "0-thing pushed" case, and "the list of things
pushed that is given to the hook happens to be empty" is an obvious
natural fallout.


Personally I think it should be mentioned in that paragraph, which is
covering all the various special cases. The 'nothing' case often causes
confusion when it's not specified in documentation.



 If this hook exits with a non-zero status, 'git push' will abort
without
 pushing anything.  Information about why the push is rejected may be
sent
 to the user by writing to standard error.

--


It may be that the documentation should include the caveat

   "Hooks, when enabled, are executed unconditionally by their calling
   functions.
Script writers should ensure they handle all conditions."

somewhere near the top of the page to cover all hooks, which IIRC
started David's journey. That would allow my second paragraph
"Likewise.." to be dropped.

Philip
--
[apologies for any whitespace damage]

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH/RFC 0/6] reuse deltas found by bitmaps

2014-03-26 Thread Jeff King
On Wed, Mar 26, 2014 at 02:13:00PM -0400, Jeff King wrote:

> So I think the next steps are probably:
> 
>   1. Measure the "all objects are preferred bases" approach and confirm
>  that it is bad.

Below is a very rough patch to accomplish this. It just traverses the
"have" bitmap and adds every object with the "exclude" flag. The result
is as comically bad as I expected.

For a big fetch, it seems like it's working (numbers against v1.9.0):

  5311.31: server (128 days)   4.49(7.35+0.23)   4.98(6.82+3.31) +10.9%
  5311.32: size   (128 days) 25.8M 32.0M +24.2%
  5311.33: client (128 days)   7.17(7.38+0.20)   7.33(7.90+0.20) +2.2%

A modest increase in CPU time, and we get back most of our size
(remember that our "bad" case here is ~80M).

But for a small fetch...

  5311.3: server   (1 days)0.20(0.17+0.03)   4.39(4.03+6.59) +2095.0%
  5311.4: size (1 days)  57.2K 59.5K +4.1%
  5311.5: client   (1 days)0.08(0.08+0.00)   0.08(0.08+0.00) +0.0%

Yikes. Besides spending lots of CPU on handling the enlarged object
list, notice that we still only dropped the size in the 128-day case to
32M. Which is almost exactly what the earlier "reuse on-disk deltas"
patch achieved.

What I think is happening is that we manage to reuse those on-disk
deltas (since they are now preferred bases, and we know we can). But we
never actually come up with any _new_ deltas, because the search window
is overwhelmed with candidates. So not only do we waste a huge amount of
CPU, but we just end up at the same not-quite-optimal result as before.

So this is a dead end, but I think it was good to double-check that.

The patch below is messy and would probably be better split into a few
patches, but I don't expect anyone to apply it (or even read it,
really). It's just for reference.

---
diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c
index 0ee5f1f..1a5d401 100644
--- a/builtin/pack-objects.c
+++ b/builtin/pack-objects.c
@@ -1026,7 +1026,7 @@ static int add_object_entry_from_bitmap(const unsigned 
char *sha1,
if (have_duplicate_entry(sha1, 0, &index_pos))
return 0;
 
-   create_object_entry(sha1, type, name_hash, 0, 0, index_pos, pack, 
offset);
+   create_object_entry(sha1, type, name_hash, flags, 0, index_pos, pack, 
offset);
 
display_progress(progress_state, to_pack.nr_objects);
return 1;
@@ -2436,6 +2436,7 @@ static int get_object_list_from_bitmap(struct rev_info 
*revs)
}
 
traverse_bitmap_commit_list(&add_object_entry_from_bitmap);
+   bitmap_have_foreach(&add_object_entry_from_bitmap);
return 0;
 }
 
diff --git a/pack-bitmap.c b/pack-bitmap.c
index 1bae7e8..f4e30f5 100644
--- a/pack-bitmap.c
+++ b/pack-bitmap.c
@@ -605,6 +605,7 @@ static void show_objects_for_type(
struct bitmap *objects,
struct ewah_bitmap *type_filter,
enum object_type object_type,
+   int flags,
show_reachable_fn show_reach)
 {
size_t pos = 0, i = 0;
@@ -613,9 +614,6 @@ static void show_objects_for_type(
struct ewah_iterator it;
eword_t filter;
 
-   if (bitmap_git.reuse_objects == bitmap_git.pack->num_objects)
-   return;
-
ewah_iterator_init(&it, type_filter);
 
while (i < objects->word_alloc && ewah_iterator_next(&filter, &it)) {
@@ -640,7 +638,7 @@ static void show_objects_for_type(
if (bitmap_git.hashes)
hash = ntohl(bitmap_git.hashes[entry->nr]);
 
-   show_reach(sha1, object_type, 0, hash, bitmap_git.pack, 
entry->offset);
+   show_reach(sha1, object_type, flags, hash, 
bitmap_git.pack, entry->offset);
}
 
pos += BITS_IN_WORD;
@@ -816,14 +814,17 @@ void traverse_bitmap_commit_list(show_reachable_fn 
show_reachable)
 {
assert(bitmap_git.result);
 
+   if (bitmap_git.reuse_objects == bitmap_git.pack->num_objects)
+   return;
+
show_objects_for_type(bitmap_git.result, bitmap_git.commits,
-   OBJ_COMMIT, show_reachable);
+   OBJ_COMMIT, 0, show_reachable);
show_objects_for_type(bitmap_git.result, bitmap_git.trees,
-   OBJ_TREE, show_reachable);
+   OBJ_TREE, 0, show_reachable);
show_objects_for_type(bitmap_git.result, bitmap_git.blobs,
-   OBJ_BLOB, show_reachable);
+   OBJ_BLOB, 0, show_reachable);
show_objects_for_type(bitmap_git.result, bitmap_git.tags,
-   OBJ_TAG, show_reachable);
+   OBJ_TAG, 0, show_reachable);
 
show_extended_objects(bitmap_git.result, show_reachable);
 
@@ -1090,3 +1091,18 @@ int bitmap_have(const unsigned char *sha1)
 
return bitmap_get(bitmap_git.haves, pos);
 }
+
+void bitmap_have_foreach(show_reachable_fn show_reachable)
+{
+   if (!bitmap_git.haves)
+   return;
+
+   show_object

  1   2   >