Re: [PATCH 2/7] move setting of object-type to alloc_* functions

2014-07-13 Thread Jeff King
On Sat, Jul 12, 2014 at 02:05:39PM -0400, Jeff King wrote:

  I don't particularly like 'flag' here. (not a massive dislike, mind you:)
  
  Perhaps: flag-object_type, type-node_type?
  Or, if that's too verbose, maybe just: flag-type, type-node?
 
 Me either, but as you noticed, type was taken. Your suggestions seem
 fine. We could also just do away with the macro as discussed earlier (we
 already do in the commit_node case, anyway...).

Thinking on this more, writing out the definitions is the only sane
thing to do here, now that alloc_commit_node does not use the macro.
Otherwise you are inviting people to modify the macro, but fail to
notice that the commit allocator also needs updating.

Here's a re-roll. The interesting bit is the addition of the second
patch (but the rest needed to be rebased on top).

  [1/8]: alloc.c: remove the alloc_raw_commit_node() function
  [2/8]: alloc: write out allocator definitions
  [3/8]: move setting of object-type to alloc_* functions
  [4/8]: parse_object_buffer: do not set object type
  [5/8]: add object_as_type helper for casting objects
  [6/8]: alloc: factor out commit index
  [7/8]: object_as_type: set commit index
  [8/8]: diff-tree: avoid lookup_unknown_object

-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 v2 1/8] alloc.c: remove the alloc_raw_commit_node() function

2014-07-13 Thread Jeff King
From: Ramsay Jones ram...@ramsay1.demon.co.uk

In order to encapsulate the setting of the unique commit index, commit
969eba63 (commit: push commit_index update into alloc_commit_node,
10-06-2014) introduced a (logically private) intermediary allocator
function. However, this function (alloc_raw_commit_node()) was declared
as a public function, which undermines its entire purpose.

Introduce an inline function, alloc_node(), which implements the main
logic of the allocator used by DEFINE_ALLOCATOR, and redefine the macro
in terms of the new function. In addition, use the new function in the
implementation of the alloc_commit_node() allocator, rather than the
intermediary allocator, which can now be removed.

Noticed by sparse (symbol 'alloc_raw_commit_node' was not declared.
Should it be static?).

Signed-off-by: Ramsay Jones ram...@ramsay1.demon.co.uk
Signed-off-by: Jeff King p...@peff.net
---
 alloc.c | 47 +--
 1 file changed, 29 insertions(+), 18 deletions(-)

diff --git a/alloc.c b/alloc.c
index eb22a45..d7c3605 100644
--- a/alloc.c
+++ b/alloc.c
@@ -19,22 +19,10 @@
 #define BLOCKING 1024
 
 #define DEFINE_ALLOCATOR(name, type)   \
-static unsigned int name##_allocs; \
+static struct alloc_state name##_state;\
 void *alloc_##name##_node(void)\
 {  \
-   static int nr;  \
-   static type *block; \
-   void *ret;  \
-   \
-   if (!nr) {  \
-   nr = BLOCKING;  \
-   block = xmalloc(BLOCKING * sizeof(type));   \
-   }   \
-   nr--;   \
-   name##_allocs++;\
-   ret = block++;  \
-   memset(ret, 0, sizeof(type));   \
-   return ret; \
+   return alloc_node(name##_state, sizeof(type)); \
 }
 
 union any_object {
@@ -45,16 +33,39 @@ union any_object {
struct tag tag;
 };
 
+struct alloc_state {
+   int count; /* total number of nodes allocated */
+   int nr;/* number of nodes left in current allocation */
+   void *p;   /* first free node in current allocation */
+};
+
+static inline void *alloc_node(struct alloc_state *s, size_t node_size)
+{
+   void *ret;
+
+   if (!s-nr) {
+   s-nr = BLOCKING;
+   s-p = xmalloc(BLOCKING * node_size);
+   }
+   s-nr--;
+   s-count++;
+   ret = s-p;
+   s-p = (char *)s-p + node_size;
+   memset(ret, 0, node_size);
+   return ret;
+}
+
 DEFINE_ALLOCATOR(blob, struct blob)
 DEFINE_ALLOCATOR(tree, struct tree)
-DEFINE_ALLOCATOR(raw_commit, struct commit)
 DEFINE_ALLOCATOR(tag, struct tag)
 DEFINE_ALLOCATOR(object, union any_object)
 
+static struct alloc_state commit_state;
+
 void *alloc_commit_node(void)
 {
static int commit_count;
-   struct commit *c = alloc_raw_commit_node();
+   struct commit *c = alloc_node(commit_state, sizeof(struct commit));
c-index = commit_count++;
return c;
 }
@@ -66,13 +77,13 @@ static void report(const char *name, unsigned int count, 
size_t size)
 }
 
 #define REPORT(name, type) \
-report(#name, name##_allocs, name##_allocs * sizeof(type)  10)
+report(#name, name##_state.count, name##_state.count * sizeof(type)  10)
 
 void alloc_report(void)
 {
REPORT(blob, struct blob);
REPORT(tree, struct tree);
-   REPORT(raw_commit, struct commit);
+   REPORT(commit, struct commit);
REPORT(tag, struct tag);
REPORT(object, union any_object);
 }
-- 
2.0.0.566.gfe3e6b2

--
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 2/8] alloc: write out allocator definitions

2014-07-13 Thread Jeff King
Because the allocator functions for tree, blobs, etc are all
very similar, we originally used a macro to avoid repeating
ourselves. Since the prior commit, though, the heavy lifting
is done by an inline helper function.  The macro does still
save us a few lines, but at some readability cost.  It
obfuscates the function definitions (and makes them hard to
find via grep).

Much worse, though, is the fact that it isn't used
consistently for all allocators. Somebody coming later may
be tempted to modify DEFINE_ALLOCATOR, but they would miss
alloc_commit_node, which is treated specially.

Let's just drop the macro and write everything out
explicitly.

Signed-off-by: Jeff King p...@peff.net
---
 alloc.c | 38 +++---
 1 file changed, 27 insertions(+), 11 deletions(-)

diff --git a/alloc.c b/alloc.c
index d7c3605..03e458b 100644
--- a/alloc.c
+++ b/alloc.c
@@ -18,13 +18,6 @@
 
 #define BLOCKING 1024
 
-#define DEFINE_ALLOCATOR(name, type)   \
-static struct alloc_state name##_state;\
-void *alloc_##name##_node(void)\
-{  \
-   return alloc_node(name##_state, sizeof(type)); \
-}
-
 union any_object {
struct object object;
struct blob blob;
@@ -55,10 +48,33 @@ static inline void *alloc_node(struct alloc_state *s, 
size_t node_size)
return ret;
 }
 
-DEFINE_ALLOCATOR(blob, struct blob)
-DEFINE_ALLOCATOR(tree, struct tree)
-DEFINE_ALLOCATOR(tag, struct tag)
-DEFINE_ALLOCATOR(object, union any_object)
+static struct alloc_state blob_state;
+void *alloc_blob_node(void)
+{
+   struct blob *b = alloc_node(blob_state, sizeof(struct blob));
+   return b;
+}
+
+static struct alloc_state tree_state;
+void *alloc_tree_node(void)
+{
+   struct tree *t = alloc_node(tree_state, sizeof(struct tree));
+   return t;
+}
+
+static struct alloc_state tag_state;
+void *alloc_tag_node(void)
+{
+   struct tag *t = alloc_node(tag_state, sizeof(struct tag));
+   return t;
+}
+
+static struct alloc_state object_state;
+void *alloc_object_node(void)
+{
+   struct object *obj = alloc_node(object_state, sizeof(union 
any_object));
+   return obj;
+}
 
 static struct alloc_state commit_state;
 
-- 
2.0.0.566.gfe3e6b2

--
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 4/8] parse_object_buffer: do not set object type

2014-07-13 Thread Jeff King
The only way that obj can be non-NULL is if it came from
one of the lookup_* functions. These functions always ensure
that the object has the expected type (and return NULL
otherwise), so there is no need for us to set the type.

Signed-off-by: Jeff King p...@peff.net
---
 object.c | 2 --
 1 file changed, 2 deletions(-)

diff --git a/object.c b/object.c
index a950b85..472aa8d 100644
--- a/object.c
+++ b/object.c
@@ -213,8 +213,6 @@ struct object *parse_object_buffer(const unsigned char 
*sha1, enum object_type t
warning(object %s has unknown type id %d, sha1_to_hex(sha1), 
type);
obj = NULL;
}
-   if (obj  obj-type == OBJ_NONE)
-   obj-type = type;
return obj;
 }
 
-- 
2.0.0.566.gfe3e6b2

--
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 5/8] add object_as_type helper for casting objects

2014-07-13 Thread Jeff King
When we call lookup_commit, lookup_tree, etc, the logic goes
something like:

  1. Look for an existing object struct. If we don't have
 one, allocate and return a new one.

  2. Double check that any object we have is the expected
 type (and complain and return NULL otherwise).

  3. Convert an object with type OBJ_NONE (from a prior
 call to lookup_unknown_object) to the expected type.

We can encapsulate steps 2 and 3 in a helper function which
checks whether we have the expected object type, converts
OBJ_NONE as appropriate, and returns the object.

Not only does this shorten the code, but it also provides
one central location for converting OBJ_NONE objects into
objects of other types. Future patches will use that to
enforce type-specific invariants.

Since this is a refactoring, we would want it to behave
exactly as the current code. It takes a little reasoning to
see that this is the case:

  - for lookup_{commit,tree,etc} functions, we are just
pulling steps 2 and 3 into a function that does the same
thing.

  - for the call in peel_object, we currently only do step 3
(but we want to consolidate it with the others, as
mentioned above). However, step 2 is a noop here, as the
surrounding conditional makes sure we have OBJ_NONE
(which we want to keep to avoid an extraneous call to
sha1_object_info).

  - for the call in lookup_commit_reference_gently, we are
currently doing step 2 but not step 3. However, step 3
is a noop here. The object we got will have just come
from deref_tag, which must have figured out the type for
each object in order to know when to stop peeling.
Therefore the type will never be OBJ_NONE.

Signed-off-by: Jeff King p...@peff.net
---
 blob.c   |  9 +
 commit.c | 19 ++-
 object.c | 17 +
 object.h |  2 ++
 refs.c   |  3 +--
 tag.c|  9 +
 tree.c   |  9 +
 7 files changed, 25 insertions(+), 43 deletions(-)

diff --git a/blob.c b/blob.c
index 5720a38..1fcb8e4 100644
--- a/blob.c
+++ b/blob.c
@@ -8,14 +8,7 @@ struct blob *lookup_blob(const unsigned char *sha1)
struct object *obj = lookup_object(sha1);
if (!obj)
return create_object(sha1, alloc_blob_node());
-   if (!obj-type)
-   obj-type = OBJ_BLOB;
-   if (obj-type != OBJ_BLOB) {
-   error(Object %s is a %s, not a blob,
- sha1_to_hex(sha1), typename(obj-type));
-   return NULL;
-   }
-   return (struct blob *) obj;
+   return object_as_type(obj, OBJ_BLOB, 0);
 }
 
 int parse_blob_buffer(struct blob *item, void *buffer, unsigned long size)
diff --git a/commit.c b/commit.c
index c1815c8..08816d3 100644
--- a/commit.c
+++ b/commit.c
@@ -18,19 +18,6 @@ int save_commit_buffer = 1;
 
 const char *commit_type = commit;
 
-static struct commit *check_commit(struct object *obj,
-  const unsigned char *sha1,
-  int quiet)
-{
-   if (obj-type != OBJ_COMMIT) {
-   if (!quiet)
-   error(Object %s is a %s, not a commit,
- sha1_to_hex(sha1), typename(obj-type));
-   return NULL;
-   }
-   return (struct commit *) obj;
-}
-
 struct commit *lookup_commit_reference_gently(const unsigned char *sha1,
  int quiet)
 {
@@ -38,7 +25,7 @@ struct commit *lookup_commit_reference_gently(const unsigned 
char *sha1,
 
if (!obj)
return NULL;
-   return check_commit(obj, sha1, quiet);
+   return object_as_type(obj, OBJ_COMMIT, quiet);
 }
 
 struct commit *lookup_commit_reference(const unsigned char *sha1)
@@ -63,9 +50,7 @@ struct commit *lookup_commit(const unsigned char *sha1)
struct object *obj = lookup_object(sha1);
if (!obj)
return create_object(sha1, alloc_commit_node());
-   if (!obj-type)
-   obj-type = OBJ_COMMIT;
-   return check_commit(obj, sha1, 0);
+   return object_as_type(obj, OBJ_COMMIT, 0);
 }
 
 struct commit *lookup_commit_reference_by_name(const char *name)
diff --git a/object.c b/object.c
index 472aa8d..b2319f6 100644
--- a/object.c
+++ b/object.c
@@ -158,6 +158,23 @@ void *create_object(const unsigned char *sha1, void *o)
return obj;
 }
 
+void *object_as_type(struct object *obj, enum object_type type, int quiet)
+{
+   if (obj-type == type)
+   return obj;
+   else if (obj-type == OBJ_NONE) {
+   obj-type = type;
+   return obj;
+   }
+   else {
+   if (!quiet)
+   error(object %s is a %s, not a %s,
+ sha1_to_hex(obj-sha1),
+ typename(obj-type), typename(type));
+   return NULL;
+   }
+}
+
 struct object *lookup_unknown_object(const unsigned char *sha1)
 {
struct object *obj 

[PATCH v2 6/8] alloc: factor out commit index

2014-07-13 Thread Jeff King
We keep a static counter to set the commit index on newly
allocated objects. However, since we also need to set the
index on any_objects which are converted to commits, let's
make the counter available as a public function.

While we're moving it, let's make sure the counter is
allocated as an unsigned integer to match the index field in
struct commit.

Signed-off-by: Jeff King p...@peff.net
---
 alloc.c | 9 +++--
 cache.h | 1 +
 2 files changed, 8 insertions(+), 2 deletions(-)

diff --git a/alloc.c b/alloc.c
index fd2e32d..12afadf 100644
--- a/alloc.c
+++ b/alloc.c
@@ -82,12 +82,17 @@ void *alloc_object_node(void)
 
 static struct alloc_state commit_state;
 
+unsigned int alloc_commit_index(void)
+{
+   static unsigned int count;
+   return count++;
+}
+
 void *alloc_commit_node(void)
 {
-   static int commit_count;
struct commit *c = alloc_node(commit_state, sizeof(struct commit));
c-object.type = OBJ_COMMIT;
-   c-index = commit_count++;
+   c-index = alloc_commit_index();
return c;
 }
 
diff --git a/cache.h b/cache.h
index 44aa439..ba68e11 100644
--- a/cache.h
+++ b/cache.h
@@ -1380,6 +1380,7 @@ extern void *alloc_commit_node(void);
 extern void *alloc_tag_node(void);
 extern void *alloc_object_node(void);
 extern void alloc_report(void);
+extern unsigned int alloc_commit_index(void);
 
 /* trace.c */
 __attribute__((format (printf, 1, 2)))
-- 
2.0.0.566.gfe3e6b2

--
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 3/8] move setting of object-type to alloc_* functions

2014-07-13 Thread Jeff King
The struct object type implements basic object
polymorphism.  Individual instances are allocated as
concrete types (or as a union type that can store any
object), and a struct object * can be cast into its real
type after examining its type enum.  This means it is
dangerous to have a type field that does not match the
allocation (e.g., setting the type field of a struct blob
to OBJ_COMMIT would mean that a reader might read past the
allocated memory).

In most of the current code this is not a problem; the first
thing we do after allocating an object is usually to set its
type field by passing it to create_object. However, the
virtual commits we create in merge-recursive.c do not ever
get their type set. This does not seem to have caused
problems in practice, though (presumably because we always
pass around a struct commit pointer and never even look at
the type).

We can fix this oversight and also make it harder for future
code to get it wrong by setting the type directly in the
object allocation functions.

This will also make it easier to fix problems with commit
index allocation, as we know that any object allocated by
alloc_commit_node will meet the invariant that an object
with an OBJ_COMMIT type field will have a unique index
number.

Signed-off-by: Jeff King p...@peff.net
---
 alloc.c | 5 +
 blob.c  | 2 +-
 builtin/blame.c | 1 -
 commit.c| 6 ++
 object.c| 5 ++---
 object.h| 2 +-
 tag.c   | 2 +-
 tree.c  | 2 +-
 8 files changed, 13 insertions(+), 12 deletions(-)

diff --git a/alloc.c b/alloc.c
index 03e458b..fd2e32d 100644
--- a/alloc.c
+++ b/alloc.c
@@ -52,6 +52,7 @@ static struct alloc_state blob_state;
 void *alloc_blob_node(void)
 {
struct blob *b = alloc_node(blob_state, sizeof(struct blob));
+   b-object.type = OBJ_BLOB;
return b;
 }
 
@@ -59,6 +60,7 @@ static struct alloc_state tree_state;
 void *alloc_tree_node(void)
 {
struct tree *t = alloc_node(tree_state, sizeof(struct tree));
+   t-object.type = OBJ_TREE;
return t;
 }
 
@@ -66,6 +68,7 @@ static struct alloc_state tag_state;
 void *alloc_tag_node(void)
 {
struct tag *t = alloc_node(tag_state, sizeof(struct tag));
+   t-object.type = OBJ_TAG;
return t;
 }
 
@@ -73,6 +76,7 @@ static struct alloc_state object_state;
 void *alloc_object_node(void)
 {
struct object *obj = alloc_node(object_state, sizeof(union 
any_object));
+   obj-type = OBJ_NONE;
return obj;
 }
 
@@ -82,6 +86,7 @@ void *alloc_commit_node(void)
 {
static int commit_count;
struct commit *c = alloc_node(commit_state, sizeof(struct commit));
+   c-object.type = OBJ_COMMIT;
c-index = commit_count++;
return c;
 }
diff --git a/blob.c b/blob.c
index ae320bd..5720a38 100644
--- a/blob.c
+++ b/blob.c
@@ -7,7 +7,7 @@ struct blob *lookup_blob(const unsigned char *sha1)
 {
struct object *obj = lookup_object(sha1);
if (!obj)
-   return create_object(sha1, OBJ_BLOB, alloc_blob_node());
+   return create_object(sha1, alloc_blob_node());
if (!obj-type)
obj-type = OBJ_BLOB;
if (obj-type != OBJ_BLOB) {
diff --git a/builtin/blame.c b/builtin/blame.c
index d3b256e..8f3e311 100644
--- a/builtin/blame.c
+++ b/builtin/blame.c
@@ -2287,7 +2287,6 @@ static struct commit *fake_working_tree_commit(struct 
diff_options *opt,
commit = alloc_commit_node();
commit-object.parsed = 1;
commit-date = now;
-   commit-object.type = OBJ_COMMIT;
parent_tail = commit-parents;
 
if (!resolve_ref_unsafe(HEAD, head_sha1, 1, NULL))
diff --git a/commit.c b/commit.c
index acb74b5..c1815c8 100644
--- a/commit.c
+++ b/commit.c
@@ -61,10 +61,8 @@ struct commit *lookup_commit_or_die(const unsigned char 
*sha1, const char *ref_n
 struct commit *lookup_commit(const unsigned char *sha1)
 {
struct object *obj = lookup_object(sha1);
-   if (!obj) {
-   struct commit *c = alloc_commit_node();
-   return create_object(sha1, OBJ_COMMIT, c);
-   }
+   if (!obj)
+   return create_object(sha1, alloc_commit_node());
if (!obj-type)
obj-type = OBJ_COMMIT;
return check_commit(obj, sha1, 0);
diff --git a/object.c b/object.c
index 9c31e9a..a950b85 100644
--- a/object.c
+++ b/object.c
@@ -141,13 +141,12 @@ static void grow_object_hash(void)
obj_hash_size = new_hash_size;
 }
 
-void *create_object(const unsigned char *sha1, int type, void *o)
+void *create_object(const unsigned char *sha1, void *o)
 {
struct object *obj = o;
 
obj-parsed = 0;
obj-used = 0;
-   obj-type = type;
obj-flags = 0;
hashcpy(obj-sha1, sha1);
 
@@ -163,7 +162,7 @@ struct object *lookup_unknown_object(const unsigned char 
*sha1)
 {
struct object *obj = lookup_object(sha1);
if (!obj)
-   obj = create_object(sha1, 

[PATCH v2 8/8] diff-tree: avoid lookup_unknown_object

2014-07-13 Thread Jeff King
We generally want to avoid lookup_unknown_object, because it
results in allocating more memory for the object than may be
strictly necessary.

In this case, it is used to check whether we have an
already-parsed object before calling parse_object, to save
us from reading the object from disk. Using lookup_object
would be fine for that purpose, but we can take it a step
further. Since this code was written, parse_object already
learned the check lookup_object optimization, so we can
simply call parse_object directly.

Signed-off-by: Jeff King p...@peff.net
---
 builtin/diff-tree.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/builtin/diff-tree.c b/builtin/diff-tree.c
index ce0e019..1c4ad62 100644
--- a/builtin/diff-tree.c
+++ b/builtin/diff-tree.c
@@ -68,9 +68,7 @@ static int diff_tree_stdin(char *line)
line[len-1] = 0;
if (get_sha1_hex(line, sha1))
return -1;
-   obj = lookup_unknown_object(sha1);
-   if (!obj || !obj-parsed)
-   obj = parse_object(sha1);
+   obj = parse_object(sha1);
if (!obj)
return -1;
if (obj-type == OBJ_COMMIT)
-- 
2.0.0.566.gfe3e6b2
--
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 7/8] object_as_type: set commit index

2014-07-13 Thread Jeff King
The point of the index field of struct commit is that
every allocated commit would have one. It is supposed to be
an invariant that whenever object-type is set to
OBJ_COMMIT, we have a unique index.

Commit 969eba6 (commit: push commit_index update into
alloc_commit_node, 2014-06-10) covered this case for
newly-allocated commits. However, we may also allocate an
unknown object via lookup_unknown_object, and only later
convert it to a commit. We must make sure that we set the
commit index when we switch the type field.

Signed-off-by: Jeff King p...@peff.net
---
 object.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/object.c b/object.c
index b2319f6..69fbbbf 100644
--- a/object.c
+++ b/object.c
@@ -163,6 +163,8 @@ void *object_as_type(struct object *obj, enum object_type 
type, int quiet)
if (obj-type == type)
return obj;
else if (obj-type == OBJ_NONE) {
+   if (type == OBJ_COMMIT)
+   ((struct commit *)obj)-index = alloc_commit_index();
obj-type = type;
return obj;
}
-- 
2.0.0.566.gfe3e6b2

--
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] http: Add Accept-Language header if possible

2014-07-13 Thread Yi, EungJun
2014-07-13 13:26 GMT+09:00 Eric Sunshine sunsh...@sunshineco.com:
 +   /* Decide the precision for q-factor on number of preferred 
 languages. */
 +   if (num_langs + 1  100) { /* +1 is for '*' */
 +   q_precision = 0.001;
 +   q_format = ; q=%.3f;
 +   } else if (num_langs + 1  10) { /* +1 is for '*' */
 +   q_precision = 0.01;
 +   q_format = ; q=%.2f;
 +   }

 It might make sense to have a final 'else' here which sets these
 variables for the 0.1 case so that the reader of the code doesn't have
 to refer back to the top of the function to figure out what is going
 on.

 } else {
 q_precision = 0.1;
 q_format = ; q=%.1f;
 }

 Better yet, would it be possible to compute these values rather than
 having to set them manually via a cascading if-chain?

I think it is possible like this:

num_langs += 1; /* for '*' */
decimal_places = 1 + (num_langs  10) + (num_langs  100);
snprintf(q_format, sizeof(q_format), ; q=%%.%df, decimal_places);
for (q_precision = 1.0; decimal_places--  0;) q_precision /= 10;

Does this one look better than before? I'm not sure which one is better.

ps. The last line can be simpler by using pow() but I'm not sure it is
okay to include math.h.
--
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: [Bug] data loss with cyclic alternates

2014-07-13 Thread Ephrim Khong

Am 11.07.14 18:01, schrieb Junio C Hamano:

Ephrim Khong dr.kh...@gmail.com writes:


git seems to have issues with alternates when cycles are present (repo
A has B/objects as alternates, B has A/objects as alternates).


Yeah, don't do that.  A thinks eh, the other guy must have it and
B thinks the same.  In general, do not prune or gc a repository
other repositories borrow from, even if there is no cycle, because
the borrowee does not know anythning about objects that it itself no
longer needs but are still needed by its borrowers.


It seems that there is a safeguard against this in sha1_file.c, 
link_alt_odb_entry(), that doesn't work as intended:


if (!strcmp(ent-base, objdir)) {
free(ent);
return -1;
}

However, printf-debugging tells me that ent-base is absolute and objdir 
is relative (.git/objects) at this point, so the strings are different 
even though the files are the same.


I never submitted a patch to git. Do you think someone can fix this 
hickup, otherwise I'll give it a shot next week.



--
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 v2 03/19] rebase -i: reword executes pre-commit hook on interim commit

2014-07-13 Thread Fabian Ruch
Hi Junio,

Junio C Hamano writes:
 Fabian Ruch baf...@gmail.com writes:
 The to-do list command `reword` replays a commit like `pick` but lets
 the user also edit the commit's log message. This happens in two
 steps. Firstly, the named commit is cherry-picked. Secondly, the
 commit created in the first step is amended using an unchanged index
 to edit the log message. The pre-commit hook is meant to verify the
 changes introduced by a commit (for instance, catching inserted
 trailing white space). Since the committed tree is not changed
 between the two steps, do not execute the pre-commit hook in the
 second step.
 
 It is not like the second step is built as a child commit of the
 result from the first step, recording the same tree without any
 change.  Why is it a good thing not to run the pre-commit hook (or
 other hooks for that matter)?  After all, the result of the second
 step is what is recorded in the final history; it just feels wrong
 not to test that one, even if it were a good idea to test only once.

if I understand correctly, the tree of the (amended) commit isn't tested
at all by git-rebase--interactive because git-cherry-pick, and therefore
pick_one, commits with both the pre-commit and commit-msg hook disabled
(see the git commit -n command line being built in
sequencer.c#run_git_commit since revision 9fa4db5).

The commit --amend we are concerned with here amends using an
untouched tree so that the history ought to record exactly the same
trees as prior to commit --amend. If git-cherry-pick was testing the
tree, then it would be unnecessary to test the tree a second time. Since
git-cherry-pick is not testing as of yet, testing and possibly rejecting
a tree in the second step would actually be wrong. I totally neglected
to look for a test case when I submitted this patch, so I'd like to
supply one late now:

 test_expect_success 'reword a commit violating pre-commit' '
   mkdir -p .git/hooks 
   PRE_COMMIT=.git/hooks/pre-commit 
   cat $PRE_COMMIT EOF
 #!/bin/sh
 echo running pre-commit
 exit 1
 EOF
   chmod +x $PRE_COMMIT 
   test_must_fail test_commit file 
   test_commit --no-verify file 
   set_fake_editor 
   FAKE_LINES=pick 1 git rebase -i HEAD^ 
   FAKE_LINES=pick 1 git rebase -i --no-ff HEAD^ 
   FAKE_LINES=reword 1 git rebase -i HEAD^
 '

(This addition to t3404-rebase--interactive.sh is based on the test case
rebase a commit violating pre-commit; test_commit --no-verify will
be implemented the obvious way.)

In both cases, it's correct to disable the pre-commit hook when editing
the log message and it just makes sense to test changes where you make
them. Unfortunately, it is not obvious that git commit --amend merely
edits the log message rather than committing a new tree.

For what it's worth, if we were to create an empty child commit and
squash it into the parent instead of amending immediately, then
git-rebase--interactive would disable tree verification in the second
step as well. This behaviour was introduced by commit c5b09fe. Although
the change seems to have been triggered by something completely
different back then, the correctness criterion remains the same, i.e.
recording previously committed trees.

Best regards,
   Fabian

 Specify the git-commit option `--no-verify` to disable the pre-commit
 hook when editing the log message. Because `--no-verify` also skips
 the commit-msg hook, execute the hook from within
 git-rebase--interactive after the commit is created. Fortunately, the
 commit message is still available in `$GIT_DIR/COMMIT_EDITMSG` after
 git-commit terminates. Caveat: In case the commit-msg hook finds the
 new log message ill-formatted, the user is only notified of the
 failed commit-msg hook but the log message is used for the commit
 anyway. git-commit ought to offer more fine-grained control over
 which hooks are executed.

 Signed-off-by: Fabian Ruch baf...@gmail.com
 ---
  git-rebase--interactive.sh | 17 +
  1 file changed, 13 insertions(+), 4 deletions(-)

 diff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh
 index 689400e..b50770d 100644
 --- a/git-rebase--interactive.sh
 +++ b/git-rebase--interactive.sh
 @@ -504,10 +504,19 @@ do_next () {
  
  mark_action_done
  do_pick $sha1 $rest
 -git commit --allow-empty --amend --no-post-rewrite 
 ${gpg_sign_opt:+$gpg_sign_opt} || {
 -warn Could not amend commit after successfully picking 
 $sha1... $rest
 -exit_with_patch $sha1 1
 -}
 +# TODO: Work around the fact that git-commit lets us
 +# disable either both the pre-commit and the commit-msg
 +# hook or none. Disable the pre-commit hook because the
 +# tree is left unchanged but run the commit-msg hook
 +# from here because the log message is altered.
 +git commit --allow-empty --amend --no-post-rewrite -n 
 

Re: [PATCH 3/4 v6] cache-tree: subdirectory tests

2014-07-13 Thread Junio C Hamano
David Turner dtur...@twopensource.com writes:

 On Fri, 2014-07-11 at 08:40 -0700, Junio C Hamano wrote:

 In the ideal world, I think whoever tries to compare two cache-trees
 (i.e. test-dump-cache-tree) should *not* care, because we are merely
 trying to show what the correct tree object name for the node would
 be, but this is only for testing, so the best way forward would be
 to:
 
  - Stop using DRY_RUN in test-dump-cache-tree.c;
 
  - Stop the code to support DRY_RUN from cache-tree.c (nobody but
the test uses it); and
 
  - Drop the -e '#(ref)/d' from the above.
 
 I would think.

 Do you mean that I should do this in this patch set, or that it's a good
 idea for the future?

I have no strong preference either way.  Removing DRY_RUN may
simplify things in the code that gets used in the real life (as
opposed to the code that is only used during the tests), so I do not
mind it if it was done before the series as a preparation step.

 Also, if we don't use DRY_RUN, won't test-dump-cache-tree add trees to
 the actual ODB, which would be odd for a test program?

I do not see it as odd at all; after all, nobody in the real-life
uses dry-run and as you can see its use is broken, or at least is
inconsistent with the rest of the system.
--
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] http: Add Accept-Language header if possible

2014-07-13 Thread Junio C Hamano
Yi, EungJun semtlen...@gmail.com writes:

 I think it is possible like this:

 num_langs += 1; /* for '*' */
 decimal_places = 1 + (num_langs  10) + (num_langs  100);
 snprintf(q_format, sizeof(q_format), ; q=%%.%df, decimal_places);
 for (q_precision = 1.0; decimal_places--  0;) q_precision /= 10;

 Does this one look better than before? I'm not sure which one is better.

 ps. The last line can be simpler by using pow() but I'm not sure it is
 okay to include math.h.

If you do not want floating point (and I think we tend to avoid it
when we do not need it), you can realize that in your use of 0.1
and 0.01 and 0.001 there is nothing fundamentally floating-point;
you can measure how many digits below the two-byte string zero-dot
you would want upfront (by counting num_langs), and show an integer
counter zero-padded to the left to that width.

That would avoid having to even worry about a possible funny case
where subtracting 0.01 ten times from 0.1 may not yield zero (or the
result of subtracting nine times may not reach 0.01) due to rounding
errors accumulating, which was the first thing that came to my mind
when I saw your loop.



--
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 3/3 v5] tag: support configuring --sort via .gitconfig

2014-07-13 Thread Junio C Hamano
Jeff King p...@peff.net writes:

 On Fri, Jul 11, 2014 at 02:54:25PM -0700, Junio C Hamano wrote:

  Yeah, we're quite inconsistent there. In some cases we silently ignore
  something unknown (e.g., a color.diff.* slot that we do not understand),
  but in most cases if it is a config key we understand but a value we do
  not, we complain and die.
 
 Hm, that's bad---we've become less and less careful over time,
 perhaps?

 I don't think so. I think we've always been not-very-lenient with
 parsing values. Two examples:
 ...
 So I do not think we have ever had a rule, but if we did, it is probably
 silently ignore unknown keys, complain on unknown values.

Yeah, somehow I was mixing up these two cases fuzzily in my mind
while responding.  Rejecting unknown keys is bad, but we cannot be
perfectly forward compatible nor behave sensibly on unknown values
while issuing errors against known-to-be-bad values, so your rule
above sounds like the most sensible thing to do.
--
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 3/3] tag: support configuring --sort via .gitconfig

2014-07-13 Thread Junio C Hamano
Eric Sunshine sunsh...@sunshineco.com writes:

 Made parse_sort_string take a var parameter, and if given will only warn
 about invalid parameter, instead of error.

 This seems unnecessarily ugly since it's hard-coding specialized
 knowledge of the callers' error-reporting requirements into what
 should be a generalized parsing function. If you instead make
 parse_sort_string() responsible only for attempting to parse the
 value, but leave error-reporting to the callers, then this ugliness
 goes away. See below.

Yup, you are absolutely right.  Thanks for catching my silly.
--
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 v7 4/4] cache-tree: Write updated cache-tree after commit

2014-07-13 Thread Junio C Hamano
Eric Sunshine sunsh...@sunshineco.com writes:

 +   (echo p; echo 1; echo; echo s; echo n; echo y; echo q) | git commit 
 --interactive -m foo

 Broken -chain.

 Would a printf make this more readable?

 printf p\n1\n\ns\nn\ny\nq\n | git commt ... 

 Perhaps not.

But

printf %s\n p 1  s n y q

is vastly more readable, I would think.

Don't we have test_write_lines which is exactly that, though?
--
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 3/3] tag: support configuring --sort via .gitconfig

2014-07-13 Thread Jeff King
On Sun, Jul 13, 2014 at 10:10:27AM -0700, Junio C Hamano wrote:

 Eric Sunshine sunsh...@sunshineco.com writes:
 
  Made parse_sort_string take a var parameter, and if given will only warn
  about invalid parameter, instead of error.
 
  This seems unnecessarily ugly since it's hard-coding specialized
  knowledge of the callers' error-reporting requirements into what
  should be a generalized parsing function. If you instead make
  parse_sort_string() responsible only for attempting to parse the
  value, but leave error-reporting to the callers, then this ugliness
  goes away. See below.
 
 Yup, you are absolutely right.  Thanks for catching my silly.

I do not know if it is that silly. The reason we push the error
reporting down into reusable library functions, even though it is less
flexible or causes us to have quiet flags and such, is that the
library function knows more about the specific error.

In this case we are just saying your sort specification is not valid,
so it is not adding much value, and returning -1 provides enough
information for the caller to say that.  But would we eventually want to
diagnose errors more specifically? For example, in foo:refname, we
could complain that foo is not a valid sort function. And in
version:bar, we could complain that bar is not a valid sorting atom.

We can encode these error types into an enum, but it is often much
easier to report them at the time of discovery (e.g., because you have
the half-parsed string available that says foo or bar). This is a
general problem throughout a lot of our code.  In higher level languages
you might throw an exception with the error message and let the caller
decide how to report it. I wonder if it is too gross to do something
like:

  push_error_handler(collect_errors);

  /* all calls to error() in will push error text onto a stack */
  do_something();

  pop_error_handler();

  /* traverse the list, calling warning() on each, and clear the stack */
  print_errors_as_warnings();

One can imagine print_errors_as_errors, which would be useful when a
caller is not sure whether a full operation will succeed (e.g., you try
X, then Y, and only when both fail do you report an error). Or a caller
which does not call any print_error_* at all (i.e., replacing the
quiet flag that many library functions take).

I realize that I am reinventing the error-reporting wheel on a sleepy
Sunday afternoon without having thought about it much, so there is
probably some gotcha or case that makes this ugly, or perhaps it just
ends up verbose in practice. But one can dream.

-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 3/3] tag: support configuring --sort via .gitconfig

2014-07-13 Thread Jeff King
On Sun, Jul 13, 2014 at 01:33:56PM -0400, Jeff King wrote:

 I realize that I am reinventing the error-reporting wheel on a sleepy
 Sunday afternoon without having thought about it much, so there is
 probably some gotcha or case that makes this ugly, or perhaps it just
 ends up verbose in practice. But one can dream.

Just for fun...

---
diff --git a/builtin/tag.c b/builtin/tag.c
index 5e0744b..0f5be3b 100644
--- a/builtin/tag.c
+++ b/builtin/tag.c
@@ -379,7 +379,10 @@ static int git_tag_config(const char *var, const char 
*value, void *cb)
if (!strcmp(var, tag.sort)) {
if (!value)
return config_error_nonbool(var);
-   parse_sort_string(value, tag_sort);
+   set_error_routine(collect_errors);
+   if (parse_sort_string(value, tag_sort)  0)
+   print_errors(warning, #{error} in config option 
'tag.sort');
+   pop_error_routine();
return 0;
}
 
diff --git a/git-compat-util.h b/git-compat-util.h
index 9de3180..6bf91a6 100644
--- a/git-compat-util.h
+++ b/git-compat-util.h
@@ -346,6 +346,11 @@ extern void set_die_routine(NORETURN_PTR void 
(*routine)(const char *err, va_lis
 extern void set_error_routine(void (*routine)(const char *err, va_list 
params));
 extern void set_die_is_recursing_routine(int (*routine)(void));
 
+void pop_error_routine(void);
+void collect_errors(const char *err, va_list params);
+__attribute__((format (printf, 2, 3)))
+void print_errors(void (*func)(const char *, ...), const char *fmt, ...);
+
 extern int starts_with(const char *str, const char *prefix);
 extern int ends_with(const char *str, const char *suffix);
 
diff --git a/usage.c b/usage.c
index ed14645..055ccc7 100644
--- a/usage.c
+++ b/usage.c
@@ -57,10 +57,16 @@ static int die_is_recursing_builtin(void)
  * (ugh), so keep things static. */
 static NORETURN_PTR void (*usage_routine)(const char *err, va_list params) = 
usage_builtin;
 static NORETURN_PTR void (*die_routine)(const char *err, va_list params) = 
die_builtin;
-static void (*error_routine)(const char *err, va_list params) = error_builtin;
 static void (*warn_routine)(const char *err, va_list params) = warn_builtin;
 static int (*die_is_recursing)(void) = die_is_recursing_builtin;
 
+struct error_func_list {
+   void (*func)(const char *, va_list);
+   struct error_func_list *next;
+};
+static struct error_func_list default_error_func = { error_builtin };
+static struct error_func_list *error_funcs = default_error_func;
+
 void set_die_routine(NORETURN_PTR void (*routine)(const char *err, va_list 
params))
 {
die_routine = routine;
@@ -68,7 +74,84 @@ void set_die_routine(NORETURN_PTR void (*routine)(const char 
*err, va_list param
 
 void set_error_routine(void (*routine)(const char *err, va_list params))
 {
-   error_routine = routine;
+   struct error_func_list *efl = xmalloc(sizeof(*efl));
+   efl-func = routine;
+   efl-next = error_funcs;
+   error_funcs = efl;
+}
+
+void pop_error_routine(void)
+{
+   while (error_funcs != default_error_func) {
+   struct error_func_list *efl = error_funcs;
+   error_funcs = efl-next;
+   free(efl);
+   }
+}
+
+struct error_list {
+   struct strbuf buf;
+   struct error_list *next;
+};
+struct error_list *error_list;
+struct error_list **error_list_tail = error_list;
+
+void collect_errors(const char *fmt, va_list params)
+{
+   struct error_list *err = xmalloc(sizeof(*err));
+
+   strbuf_init(err-buf, 0);
+   strbuf_vaddf(err-buf, fmt, params);
+   err-next = NULL;
+   *error_list_tail = err;
+   error_list_tail = err-next;
+}
+
+static void clear_errors(void)
+{
+   while (error_list) {
+   struct error_list *next = error_list-next;
+   strbuf_release(error_list-buf);
+   free(error_list);
+   error_list = next;
+   }
+   error_list_tail = error_list;
+}
+
+void print_errors(void (*func)(const char *, ...), const char *fmt, ...)
+{
+   struct strbuf buf = STRBUF_INIT;
+   va_list params;
+   int prefix_len, suffix_start;
+   const char *p;
+   struct error_list *el;
+
+   va_start(params, fmt);
+   strbuf_vaddf(buf, fmt, params);
+   va_end(params);
+
+   /*
+* The intent here is that callers will put #{error} in their fmt
+* string. Doing two layers of interpolation is gross, because we may
+* accidentally find #{error} in one of the substitutions, not the
+* original fmt. Ideally we would do it all in a single pass (and call
+* #{error} %M or something), but that would require extending
+* vsprintf, and there is no way to do that portably.
+*/
+   p = strstr(buf.buf, #{error});
+   if (!p)
+   die(BUG: error printer does not want to print error!?);
+   prefix_len = p - buf.buf;
+   suffix_start = 

Re: [PATCH v7 4/4] cache-tree: Write updated cache-tree after commit

2014-07-13 Thread Eric Sunshine
On Sun, Jul 13, 2014 at 1:22 PM, Junio C Hamano gits...@pobox.com wrote:
 Eric Sunshine sunsh...@sunshineco.com writes:

 +   (echo p; echo 1; echo; echo s; echo n; echo y; echo q) | git commit 
 --interactive -m foo

 Broken -chain.

 Would a printf make this more readable?

 printf p\n1\n\ns\nn\ny\nq\n | git commt ... 

 Perhaps not.

 But

 printf %s\n p 1  s n y q

 is vastly more readable, I would think.

Yes, that's much nicer (and I should have thought of it myself
considering that I made effectively the same suggestion elsewhere
[1]).

 Don't we have test_write_lines which is exactly that, though?

Indeed, that's even better.

[1]: http://thread.gmane.org/gmane.comp.version-control.git/233260/focus=234499
--
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 2/7] move setting of object-type to alloc_* functions

2014-07-13 Thread Ramsay Jones
On 13/07/14 07:41, Jeff King wrote:
 On Sat, Jul 12, 2014 at 02:05:39PM -0400, Jeff King wrote:
 
 I don't particularly like 'flag' here. (not a massive dislike, mind you:)

 Perhaps: flag-object_type, type-node_type?
 Or, if that's too verbose, maybe just: flag-type, type-node?

 Me either, but as you noticed, type was taken. Your suggestions seem
 fine. We could also just do away with the macro as discussed earlier (we
 already do in the commit_node case, anyway...).
 
 Thinking on this more, writing out the definitions is the only sane
 thing to do here, now that alloc_commit_node does not use the macro.
 Otherwise you are inviting people to modify the macro, but fail to
 notice that the commit allocator also needs updating.

Hmm, well I could argue that using the macro for all allocators, apart
from alloc_commit_node(), clearly shows which allocator is the odd-man
out (and conversely, that all others are the same)! :-P

No, I don't think this is a telling advantage; I don't think it makes
that much difference. (six of one, half-a-dozen of the other).

BTW, I tested the previous series on Linux 32-bit, Cygwin 32-bit, MinGW
32-bit and Cygwin 64-bit. (I can't test on Linux 64-bit, since I can't
get Linux installed on my new laptop :( ). Admittedly, the testing on
MinGW and Cygwin was only fairly light (it takes *hours* to run the full
testsuite, and I just don't have the time).

I was slightly concerned, when reading through this new series, that the
alloc_node() function may no longer be inlined in the new allocators.
However, I have just tested on Linux (only using gcc this time), and it
was just fine. I will test the new series on the above systems later
(probably tomorrow) but don't expect to find any problems.

 
 Here's a re-roll. The interesting bit is the addition of the second
 patch (but the rest needed to be rebased on top).

Yep, this looks good. Thanks!

 
   [1/8]: alloc.c: remove the alloc_raw_commit_node() function
   [2/8]: alloc: write out allocator definitions
   [3/8]: move setting of object-type to alloc_* functions
   [4/8]: parse_object_buffer: do not set object type
   [5/8]: add object_as_type helper for casting objects
   [6/8]: alloc: factor out commit index
   [7/8]: object_as_type: set commit index
   [8/8]: diff-tree: avoid lookup_unknown_object

ATB,
Ramsay Jones



--
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 v9 2/4] test-dump-cache-tree: invalid trees are not errors

2014-07-13 Thread David Turner
From: David Turner dtur...@twopensource.com

Do not treat known-invalid trees as errors even when their subtree_nr is
incorrect.  Because git already knows that these trees are invalid,
an incorrect subtree_nr will not cause problems.

Add a couple of comments.

Signed-off-by: David Turner dtur...@twitter.com
---
 test-dump-cache-tree.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/test-dump-cache-tree.c b/test-dump-cache-tree.c
index 47eab97..cbbbd8e 100644
--- a/test-dump-cache-tree.c
+++ b/test-dump-cache-tree.c
@@ -26,16 +26,16 @@ static int dump_cache_tree(struct cache_tree *it,
return 0;
 
if (it-entry_count  0) {
+   /* invalid */
dump_one(it, pfx, );
dump_one(ref, pfx, #(ref) );
-   if (it-subtree_nr != ref-subtree_nr)
-   errs = 1;
}
else {
dump_one(it, pfx, );
if (hashcmp(it-sha1, ref-sha1) ||
ref-entry_count != it-entry_count ||
ref-subtree_nr != it-subtree_nr) {
+   /* claims to be valid but is lying */
dump_one(ref, pfx, #(ref) );
errs = 1;
}
-- 
2.0.0.390.gcb682f8

--
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 v9 1/4] cache-tree: Create/update cache-tree on checkout

2014-07-13 Thread David Turner
From: David Turner dtur...@twopensource.com

When git checkout checks out a branch, create or update the
cache-tree so that subsequent operations are faster.

update_main_cache_tree learned a new flag, WRITE_TREE_REPAIR.  When
WRITE_TREE_REPAIR is set, portions of the cache-tree which do not
correspond to existing tree objects are invalidated (and portions which
do are marked as valid).  No new tree objects are created.

Signed-off-by: David Turner dtur...@twitter.com
---
 builtin/checkout.c|  8 
 cache-tree.c  | 12 +++-
 cache-tree.h  |  1 +
 t/t0090-cache-tree.sh | 19 ---
 4 files changed, 36 insertions(+), 4 deletions(-)

diff --git a/builtin/checkout.c b/builtin/checkout.c
index 463cfee..4f08554 100644
--- a/builtin/checkout.c
+++ b/builtin/checkout.c
@@ -553,6 +553,14 @@ static int merge_working_tree(const struct checkout_opts 
*opts,
}
}
 
+   if (!active_cache_tree)
+   active_cache_tree = cache_tree();
+
+   if (!cache_tree_fully_valid(active_cache_tree))
+   cache_tree_update(active_cache_tree,
+ (const struct cache_entry * const 
*)active_cache,
+ active_nr, WRITE_TREE_SILENT | 
WRITE_TREE_REPAIR);
+
if (write_cache(newfd, active_cache, active_nr) ||
commit_locked_index(lock_file))
die(_(unable to write new index file));
diff --git a/cache-tree.c b/cache-tree.c
index 7fa524a..f951d7d 100644
--- a/cache-tree.c
+++ b/cache-tree.c
@@ -239,9 +239,12 @@ static int update_one(struct cache_tree *it,
struct strbuf buffer;
int missing_ok = flags  WRITE_TREE_MISSING_OK;
int dryrun = flags  WRITE_TREE_DRY_RUN;
+   int repair = flags  WRITE_TREE_REPAIR;
int to_invalidate = 0;
int i;
 
+   assert(!(dryrun  repair));
+
*skip_count = 0;
 
if (0 = it-entry_count  has_sha1_file(it-sha1))
@@ -374,7 +377,14 @@ static int update_one(struct cache_tree *it,
 #endif
}
 
-   if (dryrun)
+   if (repair) {
+   unsigned char sha1[20];
+   hash_sha1_file(buffer.buf, buffer.len, tree_type, sha1);
+   if (has_sha1_file(sha1))
+   hashcpy(it-sha1, sha1);
+   else
+   to_invalidate = 1;
+   } else if (dryrun)
hash_sha1_file(buffer.buf, buffer.len, tree_type, it-sha1);
else if (write_sha1_file(buffer.buf, buffer.len, tree_type, it-sha1)) {
strbuf_release(buffer);
diff --git a/cache-tree.h b/cache-tree.h
index f1923ad..666d18f 100644
--- a/cache-tree.h
+++ b/cache-tree.h
@@ -39,6 +39,7 @@ int update_main_cache_tree(int);
 #define WRITE_TREE_IGNORE_CACHE_TREE 2
 #define WRITE_TREE_DRY_RUN 4
 #define WRITE_TREE_SILENT 8
+#define WRITE_TREE_REPAIR 16
 
 /* error return codes */
 #define WRITE_TREE_UNREADABLE_INDEX (-1)
diff --git a/t/t0090-cache-tree.sh b/t/t0090-cache-tree.sh
index 6c33e28..98fb1ab 100755
--- a/t/t0090-cache-tree.sh
+++ b/t/t0090-cache-tree.sh
@@ -44,14 +44,14 @@ test_expect_success 'read-tree HEAD establishes cache-tree' 
'
 
 test_expect_success 'git-add invalidates cache-tree' '
test_when_finished git reset --hard; git read-tree HEAD 
-   echo I changed this file  foo 
+   echo I changed this file foo 
git add foo 
test_invalid_cache_tree
 '
 
 test_expect_success 'update-index invalidates cache-tree' '
test_when_finished git reset --hard; git read-tree HEAD 
-   echo I changed this file  foo 
+   echo I changed this file foo 
git update-index --add foo 
test_invalid_cache_tree
 '
@@ -85,9 +85,22 @@ test_expect_success 'reset --hard without index gives 
cache-tree' '
test_shallow_cache_tree
 '
 
-test_expect_failure 'checkout gives cache-tree' '
+test_expect_success 'checkout gives cache-tree' '
+   git tag current 
git checkout HEAD^ 
test_shallow_cache_tree
 '
 
+test_expect_success 'checkout -b gives cache-tree' '
+   git checkout current 
+   git checkout -b prev HEAD^ 
+   test_shallow_cache_tree
+'
+
+test_expect_success 'checkout -B gives cache-tree' '
+   git checkout current 
+   git checkout -B prev HEAD^ 
+   test_shallow_cache_tree
+'
+
 test_done
-- 
2.0.0.390.gcb682f8

--
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 v9 4/4] cache-tree: Write updated cache-tree after commit

2014-07-13 Thread David Turner
From: David Turner dtur...@twopensource.com

During the commit process, update the cache-tree. Write this updated
cache-tree so that it's ready for subsequent commands.

Add test code which demonstrates that git commit now writes the cache
tree.  Make all tests test the entire cache-tree, not just the root
level.

Signed-off-by: David Turner dtur...@twitter.com
---
 builtin/commit.c  |  18 +++-
 t/t0090-cache-tree.sh | 117 +++---
 2 files changed, 119 insertions(+), 16 deletions(-)

diff --git a/builtin/commit.c b/builtin/commit.c
index 461c3b1..fd4e3bc 100644
--- a/builtin/commit.c
+++ b/builtin/commit.c
@@ -342,6 +342,17 @@ static char *prepare_index(int argc, const char **argv, 
const char *prefix,
 
discard_cache();
read_cache_from(index_lock.filename);
+   if (update_main_cache_tree(WRITE_TREE_SILENT) == 0) {
+   fd = open(index_lock.filename, O_WRONLY);
+   if (fd = 0)
+   if (write_cache(fd, active_cache, active_nr)  
0)
+   die(_(unable to write index file));
+   else
+   close_lock_file(index_lock);
+   else
+   die(_(unable to write index file));
+   } else
+   warning(_(Failed to update main cache tree));
 
commit_style = COMMIT_NORMAL;
return index_lock.filename;
@@ -383,8 +394,12 @@ static char *prepare_index(int argc, const char **argv, 
const char *prefix,
if (!only  !pathspec.nr) {
fd = hold_locked_index(index_lock, 1);
refresh_cache_or_die(refresh_flags);
-   if (active_cache_changed) {
+   if (active_cache_changed
+   || !cache_tree_fully_valid(active_cache_tree)) {
update_main_cache_tree(WRITE_TREE_SILENT);
+   active_cache_changed = 1;
+   }
+   if (active_cache_changed) {
if (write_cache(fd, active_cache, active_nr) ||
commit_locked_index(index_lock))
die(_(unable to write new_index file));
@@ -435,6 +450,7 @@ static char *prepare_index(int argc, const char **argv, 
const char *prefix,
fd = hold_locked_index(index_lock, 1);
add_remove_files(partial);
refresh_cache(REFRESH_QUIET);
+   update_main_cache_tree(WRITE_TREE_SILENT);
if (write_cache(fd, active_cache, active_nr) ||
close_lock_file(index_lock))
die(_(unable to write new_index file));
diff --git a/t/t0090-cache-tree.sh b/t/t0090-cache-tree.sh
index 3a3342e..48c4240 100755
--- a/t/t0090-cache-tree.sh
+++ b/t/t0090-cache-tree.sh
@@ -8,7 +8,7 @@ cache-tree extension.
  . ./test-lib.sh
 
 cmp_cache_tree () {
-   test-dump-cache-tree actual 
+   test-dump-cache-tree | sed -e '/#(ref)/d' actual 
sed s/$_x40/SHA/ actual filtered 
test_cmp $1 filtered
 }
@@ -16,14 +16,38 @@ cmp_cache_tree () {
 # We don't bother with actually checking the SHA1:
 # test-dump-cache-tree already verifies that all existing data is
 # correct.
-test_shallow_cache_tree () {
-   printf SHA  (%d entries, 0 subtrees)\n $(git ls-files|wc -l) expect 

+generate_expected_cache_tree_rec () {
+   dir=$1${1:+/} 
+   parent=$2 
+   # ls-files might have foo/bar, foo/bar/baz, and foo/bar/quux
+   # We want to count only foo because it's the only direct child
+   subtrees=$(git ls-files|grep /|cut -d / -f 1|uniq) 
+   subtree_count=$(echo $subtrees|awk '$1 {++c} END {print c}') 
+   entries=$(git ls-files|wc -l) 
+   printf SHA $dir (%d entries, %d subtrees)\n $entries 
$subtree_count 
+   for subtree in $subtrees
+   do
+   cd $subtree
+   generate_expected_cache_tree_rec $dir$subtree $dir || 
return 1
+   cd ..
+   done 
+   dir=$parent
+}
+
+generate_expected_cache_tree () {
+   (
+   generate_expected_cache_tree_rec
+   )
+}
+
+test_cache_tree () {
+   generate_expected_cache_tree expect 
cmp_cache_tree expect
 }
 
 test_invalid_cache_tree () {
printf invalid  %s ()\n  $@ 
expect 
-   test-dump-cache-tree | \
+   test-dump-cache-tree |
sed -n -e s/[0-9]* subtrees// -e '/#(ref)/d' -e '/^invalid /p' 
actual 
test_cmp expect actual
 }
@@ -33,14 +57,14 @@ test_no_cache_tree () {
cmp_cache_tree expect
 }
 
-test_expect_failure 'initial commit has cache-tree' '
+test_expect_success 'initial commit has cache-tree' '
test_commit foo 
-   test_shallow_cache_tree
+   test_cache_tree
 '
 
 test_expect_success 'read-tree HEAD establishes cache-tree' '
git read-tree HEAD 
-   

[PATCH v9 3/4] cache-tree: subdirectory tests

2014-07-13 Thread David Turner
From: David Turner dtur...@twopensource.com

Add tests to confirm that invalidation of subdirectories neither over-
nor under-invalidates.

Signed-off-by: David Turner dtur...@twitter.com
---
 t/t0090-cache-tree.sh | 26 +++---
 1 file changed, 23 insertions(+), 3 deletions(-)

diff --git a/t/t0090-cache-tree.sh b/t/t0090-cache-tree.sh
index 98fb1ab..3a3342e 100755
--- a/t/t0090-cache-tree.sh
+++ b/t/t0090-cache-tree.sh
@@ -22,9 +22,10 @@ test_shallow_cache_tree () {
 }
 
 test_invalid_cache_tree () {
-   echo invalid   (0 subtrees) expect 
-   printf SHA #(ref)  (%d entries, 0 subtrees)\n $(git ls-files|wc -l) 
expect 
-   cmp_cache_tree expect
+   printf invalid  %s ()\n  $@ 
expect 
+   test-dump-cache-tree | \
+   sed -n -e s/[0-9]* subtrees// -e '/#(ref)/d' -e '/^invalid /p' 
actual 
+   test_cmp expect actual
 }
 
 test_no_cache_tree () {
@@ -49,6 +50,25 @@ test_expect_success 'git-add invalidates cache-tree' '
test_invalid_cache_tree
 '
 
+test_expect_success 'git-add in subdir invalidates cache-tree' '
+   test_when_finished git reset --hard; git read-tree HEAD 
+   mkdir dirx 
+   echo I changed this file dirx/foo 
+   git add dirx/foo 
+   test_invalid_cache_tree
+'
+
+test_expect_success 'git-add in subdir does not invalidate sibling cache-tree' 
'
+   git tag no-children 
+   test_when_finished git reset --hard no-children; git read-tree HEAD 
+   mkdir dir1 dir2 
+   test_commit dir1/a 
+   test_commit dir2/b 
+   echo I changed this file dir1/a 
+   git add dir1/a 
+   test_invalid_cache_tree dir1/
+'
+
 test_expect_success 'update-index invalidates cache-tree' '
test_when_finished git reset --hard; git read-tree HEAD 
echo I changed this file foo 
-- 
2.0.0.390.gcb682f8

--
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] http: Add Accept-Language header if possible

2014-07-13 Thread Yi, EungJun
2014-07-14 1:57 GMT+09:00 Junio C Hamano gits...@pobox.com:

 If you do not want floating point (and I think we tend to avoid it
 when we do not need it), you can realize that in your use of 0.1
 and 0.01 and 0.001 there is nothing fundamentally floating-point;
 you can measure how many digits below the two-byte string zero-dot
 you would want upfront (by counting num_langs), and show an integer
 counter zero-padded to the left to that width.

 That would avoid having to even worry about a possible funny case
 where subtracting 0.01 ten times from 0.1 may not yield zero (or the
 result of subtracting nine times may not reach 0.01) due to rounding
 errors accumulating, which was the first thing that came to my mind
 when I saw your loop.

You're right; We don't need floating point numbers. I'll try to fix it.
--
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 00/14] Add submodule test harness

2014-07-13 Thread Junio C Hamano
Jens Lehmann jens.lehm...@web.de writes:

 Perhaps squashing this to 7e8e5af9 instead?

 Yes please, this is much better than my first attempt.

One thing that I found troubling is the ../../../ three levels up
is hardcoded.  Would it be always true for any value of $1?  If
the submodule is bound to the superproject at sub/dir/, not at dir/,
for example, would it have to change?

I am not saying that we must support artibrary cases, but if there
is such a limitation in the implementation, people who will use the
helper in their new tests want it at least documented, I think.

  t/lib-submodule-update.sh | 19 ---
  1 file changed, 12 insertions(+), 7 deletions(-)
 
 diff --git a/t/lib-submodule-update.sh b/t/lib-submodule-update.sh
 index e441b98..fc1da84 100755
 --- a/t/lib-submodule-update.sh
 +++ b/t/lib-submodule-update.sh
 @@ -110,18 +110,23 @@ replace_gitfile_with_git_dir () {
  }
  
  # Test that the .git directory in the submodule is unchanged (except for the
 -# core.worktree setting, which we temporarily restore). Call this function
 -# before test_submodule_content as the latter might write the index file
 -# leading to false positive index differences.
 +# core.worktree setting, which appears only in $GIT_DIR/modules/$1/config).
 +# Call this function before test_submodule_content as the latter might
 +# write the index file leading to false positive index differences.
  test_git_directory_is_unchanged () {
  (
 -cd $1 
 -git config core.worktree ../../../$1
 +cd .git/modules/$1 
 +# does core.worktree point at the right place?
 +test $(git config core.worktree) = ../../../$1 
 +# remove it temporarily before comparing, as
 +# $1/.git/config lacks it...
 +git config --unset core.worktree
  ) 
  diff -r .git/modules/$1 $1/.git 
  (
 -cd $1 
 -GIT_WORK_TREE=. git config --unset core.worktree
 +# ... and then restore.
 +cd .git/modules/$1 
 +git config core.worktree ../../../$1
  )
  }
  
 
--
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


Kindly reply

2014-07-13 Thread Carlos Ramirez



My name is Carlos Ramirez, I am lawyer here in Madrid Spain. I want to  
transfer an abandoned sum of 13.5 Millions USD to your account.50%  
will be for you. No risk involved. Contact me for more details.


Kindly reply me back to my alternative email address ( carlos...@aol.com )


Regards
Carlos Ramirez

--
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: Race condition in git push --mirror can cause silent ref rewinding

2014-07-13 Thread Alex Vandiver
On 07/02/2014 07:10 PM, Alex Vandiver wrote:
 On 07/02/2014 06:20 PM, Junio C Hamano wrote:
 Alex Vandiver a...@chmrr.net writes:

 [remote github]
 url = g...@github.com:bestpractical/rt.git
 fetch = +refs/*:refs/*
 mirror = yes

 git push github master^:master must stay a usable way to update
 the published repository to an arbitrary commit, so if set to
 mirror, do not pretend that a fetch in reverse has happened during
 'git push' will not be a solution to this issue.
 
 Hm?  I'm confused, as mirror isn't compatible with refspecs:
 
 $ git push github master^:master
 error: --mirror can't be combined with refspecs

Just following up on this -- can you clarify your statement about git
push github master^:master in light of the fact that --mirror already
disallows such?
 - Alex
--
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 2/2] dir: remove PATH_MAX limitation

2014-07-13 Thread Junio C Hamano
Duy Nguyen pclo...@gmail.com writes:

 [01/20] dir.c: coding style fix
 [02/20] dir.h: move struct exclude declaration to top level
 [03/20] prep_exclude: remove the artificial PATH_MAX limit

 ...perhaps with s/if (!dir-basebuf.alloc)/if (!dir-basebuf.buf)/

 @Duy any reason for not signing off that series?

 That series still need a lot more work, but for those first three, if
 you want to fast track, you have my sign-offs.

If it is not too much trouble, can you send only the relevant
patches (these three) with sign-off again?  I'd prefer to give
patches a new chance to be eyeballed by people, and they will tend
to have a better chance by being a smaller and an isolated topic.

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


Kindly reply

2014-07-13 Thread Carlos Ramirez



My name is Carlos Ramirez, I am lawyer here in Madrid Spain. I want to  
transfer an abandoned sum of 13.5 Millions USD to your account.50%  
will be for you. No risk involved. Contact me for more details.


Kindly reply me back to my alternative email address ( carlos...@aol.com )


Regards
Carlos Ramirez

--
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 v6 28/32] gc: style change -- no SP before closing bracket

2014-07-13 Thread Junio C Hamano
On Wed, Jul 9, 2014 at 2:47 AM, Eric Sunshine sunsh...@sunshineco.com wrote:
 On Wed, Jul 9, 2014 at 3:33 AM, Nguyễn Thái Ngọc Duy pclo...@gmail.com 
 wrote:

 Yet, there is a space after the opening '{'. So, this is now
 inconsistently formatted as:

 { foo, bar}


So, if we drop the other hunk and keep only the one below,
the patch needs to be retitled with s/bracket/parenthesis/...

 @@ -298,7 +298,7 @@ int cmd_gc(int argc, const char **argv, const char 
 *prefix)
 argv_array_pushl(pack_refs_cmd, pack-refs, --all, --prune, 
 NULL);
 argv_array_pushl(reflog, reflog, expire, --all, NULL);
 argv_array_pushl(repack, repack, -d, -l, NULL);
 -   argv_array_pushl(prune, prune, --expire, NULL );
 +   argv_array_pushl(prune, prune, --expire, NULL);
 argv_array_pushl(rerere, rerere, gc, NULL);

 git_config(gc_config, NULL);
 --
 1.9.1.346.ga2b5940
--
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 v7 00/31] Support multiple checkouts

2014-07-13 Thread Junio C Hamano
Nguyễn Thái Ngọc Duy  pclo...@gmail.com writes:

   fd = open(git_path(repos/%s/gitdir, id), O_RDONLY);
 ...
 - while (path[len - 1] == '\n' || path[len - 1] == '\r')
 + while (len  (path[len - 1] == '\n' || path[len - 1] == '\r'))
   len--;

Do we anticipate (or even allow/endorse) that end users will edit
this file with a random editor?  And, to a lessor degree, the same
question on the reading side.  Do we encourage users to directly
read from this file to learn something about their repository?

If we are the only tool that writes into this file, and if we are
the only tool to be used to read (and use) the contents of this
file, I do not see the need to cater to LF vs CRLF line endings.

--
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/RFH 0/3] stable priority-queue

2014-07-13 Thread Jeff King
As Junio and I discussed earlier in [1], this series makes the
prio_queue struct stable with respect to object insertion (which in turn
means we can use it to replace commit_list in more places).

I think everything here is correct, but the second commit fails the
final test in t5539. I think the test is just flaky (hence the RFH and
cc to Duy).

That test creates some unrelated commits in two separate repositories,
and then fetches from one to the other. Since the commit creation
happens in a subshell, the first commit in each ends up with the same
test_tick value. When fetch-pack looks at the two root commits
unrelated1 and new-too, the exact sequence of ACKs is different
depending on which one it pulls out of the queue first.

With the current code, it happens to be unrelated1 (though this is not
at all guaranteed by the prio_queue data structure, it is deterministic
for this particular sequence of input). We see the ready-ACK, and the
test succeeds.

With the stable queue, we reliably get new-too out (since it is our
local tip, it is added to the queue before we even talk to the remote).
We never see a ready-ACK, and the test fails due to the grep on the
TRACE_PACKET output at the end (the fetch itself succeeds as expected).

I'm really not quite clear on what's supposed to be going on in the
test. I can make it pass with:

diff --git a/t/t5539-fetch-http-shallow.sh b/t/t5539-fetch-http-shallow.sh
index 94553e1..b461188 100755
--- a/t/t5539-fetch-http-shallow.sh
+++ b/t/t5539-fetch-http-shallow.sh
@@ -54,6 +54,7 @@ EOF
 test_expect_success 'no shallow lines after receiving ACK ready' '
(
cd shallow 
+   test_tick 
for i in $(test_seq 15)
do
git checkout --orphan unrelated$i 

which just bumps the timestamp for the unrelated* commits (so that they
are always more recent than new-too and get picked first). I'm not
sure if that is too hacky, or if there's a more robust way to set up the
test.

Anyway, here are the patches.

  [1/3]: prio-queue: factor out compare and swap operations
  [2/3]: prio-queue: make output stable with respect to insertion
  [3/3]: paint_down_to_common: use prio_queue

-Peff

[1] http://thread.gmane.org/gmane.comp.version-control.git/252472/focus=252475
--
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/3] prio-queue: factor out compare and swap operations

2014-07-13 Thread Jeff King
When manipulating the priority queue's heap, we frequently
have to compare and swap heap entries. As we are storing
only void pointers right now, this is quite easy to do
inline in a few lines. However, when we start using a more
complicated heap entry in a future patch, that will get
longer. Factoring out these operations lets us make future
changes in one place. It also makes the code a little
shorter and more readable.

Note that we actually accept indices into the queue array
instead of pointers. This is slightly less flexible than
passing pointers-to-pointers (we could not swap items from
unrelated arrays, but we would not want to), but will make
further refactoring simpler (and lets us avoid repeating
queue-array at each callsite, which led to some long
lines).

And finally, note that we are cleaning up an accidental use
of a struct commit pointer to hold a temporary entry
during swap. Even though we currently only use this code for
commits, it is supposed to be type-agnostic. In practice
this didn't matter anyway because we never dereferenced the
commit pointer (and on most systems, the pointer values
themselves are interchangeable between types).

Signed-off-by: Jeff King p...@peff.net
---
 prio-queue.c | 49 +
 1 file changed, 25 insertions(+), 24 deletions(-)

diff --git a/prio-queue.c b/prio-queue.c
index c9f8c6d..0f4fcf2 100644
--- a/prio-queue.c
+++ b/prio-queue.c
@@ -1,18 +1,28 @@
 #include cache.h
-#include commit.h
 #include prio-queue.h
 
+static inline int compare(struct prio_queue *queue, int i, int j)
+{
+   int cmp = queue-compare(queue-array[i], queue-array[j],
+queue-cb_data);
+   return cmp;
+}
+
+static inline void swap(struct prio_queue *queue, int i, int j)
+{
+   void *tmp = queue-array[i];
+   queue-array[i] = queue-array[j];
+   queue-array[j] = tmp;
+}
+
 void prio_queue_reverse(struct prio_queue *queue)
 {
int i, j;
 
if (queue-compare != NULL)
die(BUG: prio_queue_reverse() on non-LIFO queue);
-   for (i = 0; i = (j = (queue-nr - 1) - i); i++) {
-   struct commit *swap = queue-array[i];
-   queue-array[i] = queue-array[j];
-   queue-array[j] = swap;
-   }
+   for (i = 0; i = (j = (queue-nr - 1) - i); i++)
+   swap(queue, i, j);
 }
 
 void clear_prio_queue(struct prio_queue *queue)
@@ -25,37 +35,32 @@ void clear_prio_queue(struct prio_queue *queue)
 
 void prio_queue_put(struct prio_queue *queue, void *thing)
 {
-   prio_queue_compare_fn compare = queue-compare;
int ix, parent;
 
/* Append at the end */
ALLOC_GROW(queue-array, queue-nr + 1, queue-alloc);
queue-array[queue-nr++] = thing;
-   if (!compare)
+   if (!queue-compare)
return; /* LIFO */
 
/* Bubble up the new one */
for (ix = queue-nr - 1; ix; ix = parent) {
parent = (ix - 1) / 2;
-   if (compare(queue-array[parent], queue-array[ix],
-   queue-cb_data) = 0)
+   if (compare(queue, parent, ix) = 0)
break;
 
-   thing = queue-array[parent];
-   queue-array[parent] = queue-array[ix];
-   queue-array[ix] = thing;
+   swap(queue, parent, ix);
}
 }
 
 void *prio_queue_get(struct prio_queue *queue)
 {
-   void *result, *swap;
+   void *result;
int ix, child;
-   prio_queue_compare_fn compare = queue-compare;
 
if (!queue-nr)
return NULL;
-   if (!compare)
+   if (!queue-compare)
return queue-array[--queue-nr]; /* LIFO */
 
result = queue-array[0];
@@ -67,18 +72,14 @@ void *prio_queue_get(struct prio_queue *queue)
/* Push down the one at the root */
for (ix = 0; ix * 2 + 1  queue-nr; ix = child) {
child = ix * 2 + 1; /* left */
-   if ((child + 1  queue-nr) 
-   (compare(queue-array[child], queue-array[child + 1],
-queue-cb_data) = 0))
+   if (child + 1  queue-nr 
+   compare(queue, child, child + 1) = 0)
child++; /* use right child */
 
-   if (compare(queue-array[ix], queue-array[child],
-   queue-cb_data) = 0)
+   if (compare(queue, ix, child) = 0)
break;
 
-   swap = queue-array[child];
-   queue-array[child] = queue-array[ix];
-   queue-array[ix] = swap;
+   swap(queue, child, ix);
}
return result;
 }
-- 
2.0.0.566.gfe3e6b2

--
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/3] prio-queue: make output stable with respect to insertion

2014-07-13 Thread Jeff King
If two items are added to a prio_queue and compare equal,
they currently come out in an apparently random order (this
order is deterministic for a particular sequence of
insertions and removals, but does not necessarily match the
insertion order). This makes it unlike using a date-ordered
commit_list, which is one of the main types we would like to
replace with it (because prio_queue does not suffer from
O(n) insertions).

We can make the priority queue stable by keeping an
insertion counter for each element, and using it to break
ties. This does increase the memory usage of the structure
(one int per element), but in practice it does not seem to
affect runtime. A best-of-five git rev-list --topo-order
on linux.git showed less than 1% difference (well within the
run-to-run noise).

In an ideal world, we would offer both stable and unstable
priority queues (the latter to try to maximize performance).
However, given the lack of a measurable performance
difference, it is not worth the extra code.

Signed-off-by: Jeff King p...@peff.net
---
I actually tried implementing a stable queue on top of the existing
prio-queue. However, it was quite a mess. Because prio_queue only stores
one void pointer to a thing, the stable queue has to allocate its own its
(counter,thing) pair. Doing it in a separate array doesn't work (you do
not pop them in insertion order, so you end up with holes). So you end
up storing an extra pointer, _plus_ per-entry malloc overhead.

If we really want to offer a non-stable queue (and I do not think we
do), we should probably just do two totally separate queues, or
implement the whole thing with a run-time element size member (or even
do it in macros).

I use struct assignment in the swap() function below. Do we want to
replace that with a memcpy? Presumably decent compilers can turn that
into the same code anyway, but I find the assignment more readable, and
IIRC it has been around since C89.

 prio-queue.c | 15 ++-
 prio-queue.h |  8 +++-
 2 files changed, 17 insertions(+), 6 deletions(-)

diff --git a/prio-queue.c b/prio-queue.c
index 0f4fcf2..e4365b0 100644
--- a/prio-queue.c
+++ b/prio-queue.c
@@ -3,14 +3,16 @@
 
 static inline int compare(struct prio_queue *queue, int i, int j)
 {
-   int cmp = queue-compare(queue-array[i], queue-array[j],
+   int cmp = queue-compare(queue-array[i].data, queue-array[j].data,
 queue-cb_data);
+   if (!cmp)
+   cmp = queue-array[i].ctr - queue-array[j].ctr;
return cmp;
 }
 
 static inline void swap(struct prio_queue *queue, int i, int j)
 {
-   void *tmp = queue-array[i];
+   struct prio_queue_entry tmp = queue-array[i];
queue-array[i] = queue-array[j];
queue-array[j] = tmp;
 }
@@ -31,6 +33,7 @@ void clear_prio_queue(struct prio_queue *queue)
queue-nr = 0;
queue-alloc = 0;
queue-array = NULL;
+   queue-insertion_ctr = 0;
 }
 
 void prio_queue_put(struct prio_queue *queue, void *thing)
@@ -39,7 +42,9 @@ void prio_queue_put(struct prio_queue *queue, void *thing)
 
/* Append at the end */
ALLOC_GROW(queue-array, queue-nr + 1, queue-alloc);
-   queue-array[queue-nr++] = thing;
+   queue-array[queue-nr].ctr = queue-insertion_ctr++;
+   queue-array[queue-nr].data = thing;
+   queue-nr++;
if (!queue-compare)
return; /* LIFO */
 
@@ -61,9 +66,9 @@ void *prio_queue_get(struct prio_queue *queue)
if (!queue-nr)
return NULL;
if (!queue-compare)
-   return queue-array[--queue-nr]; /* LIFO */
+   return queue-array[--queue-nr].data; /* LIFO */
 
-   result = queue-array[0];
+   result = queue-array[0].data;
if (!--queue-nr)
return result;
 
diff --git a/prio-queue.h b/prio-queue.h
index 9c3cd1f..d030ec9 100644
--- a/prio-queue.h
+++ b/prio-queue.h
@@ -21,11 +21,17 @@
  */
 typedef int (*prio_queue_compare_fn)(const void *one, const void *two, void 
*cb_data);
 
+struct prio_queue_entry {
+   unsigned ctr;
+   void *data;
+};
+
 struct prio_queue {
prio_queue_compare_fn compare;
+   unsigned insertion_ctr;
void *cb_data;
int alloc, nr;
-   void **array;
+   struct prio_queue_entry *array;
 };
 
 /*
-- 
2.0.0.566.gfe3e6b2

--
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 3/3] paint_down_to_common: use prio_queue

2014-07-13 Thread Jeff King
When we are traversing to find merge bases, we keep our
usual commit_list of commits to process, sorted by their
commit timestamp. As we add each parent to the list, we have
to spend O(width of history) to do the insertion, where
the width of history is the number of simultaneous lines of
development.

If we instead use a heap-based priority queue, we can do
these insertions in O(log width) time. This provides minor
speedups to merge-base calculations (timings in linux.git,
warm cache, best-of-five):

  [before]
  $ git merge-base HEAD v2.6.12
  real0m3.251s
  user0m3.148s
  sys 0m0.104s

  [after]
  $ git merge-base HEAD v2.6.12
  real0m3.234s
  user0m3.108s
  sys 0m0.128s

That's only an 0.5% speedup, but it does help protect us
against pathological cases.

While we are munging the interesting function, we also
take the opportunity to give it a more descriptive name, and
convert the return value to an int (we returned the first
interesting commit, but nobody ever looked at it).

Signed-off-by: Jeff King p...@peff.net
---
Same as what I posted a few weeks ago, but now we do not have to tweak
t6024 to account for the lack of stability.

 commit.c | 42 +++---
 1 file changed, 19 insertions(+), 23 deletions(-)

diff --git a/commit.c b/commit.c
index acb74b5..1fc60c0 100644
--- a/commit.c
+++ b/commit.c
@@ -786,45 +786,41 @@ void sort_in_topological_order(struct commit_list **list, 
enum rev_sort_order so
 
 static const unsigned all_flags = (PARENT1 | PARENT2 | STALE | RESULT);
 
-static struct commit *interesting(struct commit_list *list)
+static int queue_has_nonstale(struct prio_queue *queue)
 {
-   while (list) {
-   struct commit *commit = list-item;
-   list = list-next;
-   if (commit-object.flags  STALE)
-   continue;
-   return commit;
+   int i;
+   for (i = 0; i  queue-nr; i++) {
+   struct commit *commit = queue-array[i].data;
+   if (!(commit-object.flags  STALE))
+   return 1;
}
-   return NULL;
+   return 0;
 }
 
 /* all input commits in one and twos[] must have been parsed! */
 static struct commit_list *paint_down_to_common(struct commit *one, int n, 
struct commit **twos)
 {
-   struct commit_list *list = NULL;
+   struct prio_queue queue = { compare_commits_by_commit_date };
struct commit_list *result = NULL;
int i;
 
one-object.flags |= PARENT1;
-   commit_list_insert_by_date(one, list);
-   if (!n)
-   return list;
+   if (!n) {
+   commit_list_append(one, result);
+   return result;
+   }
+   prio_queue_put(queue, one);
+
for (i = 0; i  n; i++) {
twos[i]-object.flags |= PARENT2;
-   commit_list_insert_by_date(twos[i], list);
+   prio_queue_put(queue, twos[i]);
}
 
-   while (interesting(list)) {
-   struct commit *commit;
+   while (queue_has_nonstale(queue)) {
+   struct commit *commit = prio_queue_get(queue);
struct commit_list *parents;
-   struct commit_list *next;
int flags;
 
-   commit = list-item;
-   next = list-next;
-   free(list);
-   list = next;
-
flags = commit-object.flags  (PARENT1 | PARENT2 | STALE);
if (flags == (PARENT1 | PARENT2)) {
if (!(commit-object.flags  RESULT)) {
@@ -843,11 +839,11 @@ static struct commit_list *paint_down_to_common(struct 
commit *one, int n, struc
if (parse_commit(p))
return NULL;
p-object.flags |= flags;
-   commit_list_insert_by_date(p, list);
+   prio_queue_put(queue, p);
}
}
 
-   free_commit_list(list);
+   clear_prio_queue(queue);
return result;
 }
 
-- 
2.0.0.566.gfe3e6b2
--
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 2/7] move setting of object-type to alloc_* functions

2014-07-13 Thread Jeff King
On Sun, Jul 13, 2014 at 08:27:51PM +0100, Ramsay Jones wrote:

  Thinking on this more, writing out the definitions is the only sane
  thing to do here, now that alloc_commit_node does not use the macro.
  Otherwise you are inviting people to modify the macro, but fail to
  notice that the commit allocator also needs updating.
 
 Hmm, well I could argue that using the macro for all allocators, apart
 from alloc_commit_node(), clearly shows which allocator is the odd-man
 out (and conversely, that all others are the same)! :-P
 
 No, I don't think this is a telling advantage; I don't think it makes
 that much difference. (six of one, half-a-dozen of the other).

Yeah, I agree with your final statement in parentheses. I am OK with it
either way (but I have a slight preference for what I posted).

 I was slightly concerned, when reading through this new series, that the
 alloc_node() function may no longer be inlined in the new allocators.
 However, I have just tested on Linux (only using gcc this time), and it
 was just fine. I will test the new series on the above systems later
 (probably tomorrow) but don't expect to find any problems.

That should not be due to my patches (which are just expanding macros),
but rather to your 1/8, right?

I do not know that it matters that much anyway. Yes, we allocate a lot
of objects in some workloads. But I think it is not so tight a loop that
the extra function call is going to kill us (and we tend to _read_ the
allocated objects much more than we allocate them).

  Here's a re-roll. The interesting bit is the addition of the second
  patch (but the rest needed to be rebased on top).
 
 Yep, this looks good. Thanks!

Thanks for reviewing, as usual.

-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