[PATCH v3 7/8] branch.c: use 'ref-filter' APIs

2015-08-21 Thread Karthik Nayak
Make 'branch.c' use 'ref-filter' APIs for iterating through refs
sorting. This removes most of the code used in 'branch.c' replacing it
with calls to the 'ref-filter' library.

Make 'branch.c' use the 'filter_refs()' function provided by 'ref-filter'
to filter out tags based on the options set.

We provide a sorting option provided for 'branch.c' by using the sorting
options provided by 'ref-filter'.

Also remove the 'ignore' variable from ref_array_item as it was
previously used for the '--merged' option and now that is handled by
ref-filter.

The test t1430 'git branch shows badly named ref' has been changed to
check the stderr for the warning regarding the broken ref. This is
done as ref-filter throws a warning for broken refs rather than
directly printing them.

Modify documentation and add tests for the same.

Mentored-by: Christian Couder 
Mentored-by: Matthieu Moy 
Signed-off-by: Karthik Nayak 
---
 Documentation/git-branch.txt |   9 +-
 builtin/branch.c | 213 +++
 ref-filter.c |   2 +-
 ref-filter.h |   1 -
 t/t1430-bad-ref-name.sh  |   2 +-
 t/t3203-branch-output.sh |  11 +++
 6 files changed, 56 insertions(+), 182 deletions(-)

diff --git a/Documentation/git-branch.txt b/Documentation/git-branch.txt
index a67138a..897cd81 100644
--- a/Documentation/git-branch.txt
+++ b/Documentation/git-branch.txt
@@ -11,7 +11,7 @@ SYNOPSIS
 'git branch' [--color[=] | --no-color] [-r | -a]
[--list] [-v [--abbrev= | --no-abbrev]]
[--column[=] | --no-column]
-   [(--merged | --no-merged | --contains) []] [...]
+   [(--merged | --no-merged | --contains) []] [--sort=] 
[...]
 'git branch' [--set-upstream | --track | --no-track] [-l] [-f]  
[]
 'git branch' (--set-upstream-to= | -u ) []
 'git branch' --unset-upstream []
@@ -229,6 +229,13 @@ start-point is either a local or remote-tracking branch.
The new name for an existing branch. The same restrictions as for
 apply.
 
+--sort=::
+   Sort based on the key given. Prefix `-` to sort in descending
+   order of the value. You may use the --sort= option
+   multiple times, in which case the last key becomes the primary
+   key. The keys supported are the same as those in `git
+   for-each-ref`. Sort order defaults to sorting based on branch
+   type.
 
 Examples
 
diff --git a/builtin/branch.c b/builtin/branch.c
index 5cb7ef0..e0aa44c 100644
--- a/builtin/branch.c
+++ b/builtin/branch.c
@@ -270,125 +270,6 @@ static int delete_branches(int argc, const char **argv, 
int force, int kinds,
return(ret);
 }
 
-static char *resolve_symref(const char *src, const char *prefix)
-{
-   unsigned char sha1[20];
-   int flag;
-   const char *dst;
-
-   dst = resolve_ref_unsafe(src, 0, sha1, &flag);
-   if (!(dst && (flag & REF_ISSYMREF)))
-   return NULL;
-   if (prefix)
-   skip_prefix(dst, prefix, &dst);
-   return xstrdup(dst);
-}
-
-static int match_patterns(const char **pattern, const char *refname)
-{
-   if (!*pattern)
-   return 1; /* no pattern always matches */
-   while (*pattern) {
-   if (!wildmatch(*pattern, refname, 0, NULL))
-   return 1;
-   pattern++;
-   }
-   return 0;
-}
-
-/*
- * Allocate memory for a new ref_array_item and insert that into the
- * given ref_array. Doesn't take the objectname unlike
- * new_ref_array_item(). This is a temporary function which will be
- * removed when we port branch.c to use ref-filter APIs.
- */
-static struct ref_array_item *ref_array_append(struct ref_array *array, const 
char *refname)
-{
-   size_t len = strlen(refname);
-   struct ref_array_item *ref = xcalloc(1, sizeof(struct ref_array_item) + 
len + 1);
-   memcpy(ref->refname, refname, len);
-   ref->refname[len] = '\0';
-   REALLOC_ARRAY(array->items, array->nr + 1);
-   array->items[array->nr++] = ref;
-   return ref;
-}
-
-static int append_ref(const char *refname, const struct object_id *oid, int 
flags, void *cb_data)
-{
-   struct ref_filter_cbdata *cb = (struct ref_filter_cbdata *)(cb_data);
-   struct ref_filter *filter = cb->filter;
-   struct ref_array *array = cb->array;
-   struct ref_array_item *item;
-   struct commit *commit;
-   int kind, i;
-   const char *prefix, *orig_refname = refname;
-
-   static struct {
-   int kind;
-   const char *prefix;
-   } ref_kind[] = {
-   { FILTER_REFS_BRANCHES, "refs/heads/" },
-   { FILTER_REFS_REMOTES, "refs/remotes/" },
-   };
-
-   /* Detect kind */
-   for (i = 0; i < ARRAY_SIZE(ref_kind); i++) {
-   prefix = ref_kind[i].prefix;
-   if (skip_prefix(refname, prefix, &refname)) {
-   kind = ref_kind[i].kind;
-   break;
-   }
- 

[PATCH v3 8/8] branch: add '--points-at' option

2015-08-21 Thread Karthik Nayak
Add the '--points-at' option provided by 'ref-filter'. The option lets
the user to list only branches which points at the given object.

Add documentation and tests for the same.

Mentored-by: Christian Couder 
Mentored-by: Matthieu Moy 
Signed-off-by: Karthik Nayak 
---
 Documentation/git-branch.txt | 6 +-
 builtin/branch.c | 7 ++-
 t/t3203-branch-output.sh | 9 +
 3 files changed, 20 insertions(+), 2 deletions(-)

diff --git a/Documentation/git-branch.txt b/Documentation/git-branch.txt
index 897cd81..211cfc3 100644
--- a/Documentation/git-branch.txt
+++ b/Documentation/git-branch.txt
@@ -11,7 +11,8 @@ SYNOPSIS
 'git branch' [--color[=] | --no-color] [-r | -a]
[--list] [-v [--abbrev= | --no-abbrev]]
[--column[=] | --no-column]
-   [(--merged | --no-merged | --contains) []] [--sort=] 
[...]
+   [(--merged | --no-merged | --contains) []] [--sort=]
+   [--points-at ] [...]
 'git branch' [--set-upstream | --track | --no-track] [-l] [-f]  
[]
 'git branch' (--set-upstream-to= | -u ) []
 'git branch' --unset-upstream []
@@ -237,6 +238,9 @@ start-point is either a local or remote-tracking branch.
for-each-ref`. Sort order defaults to sorting based on branch
type.
 
+--points-at ::
+   Only list branches of the given object.
+
 Examples
 
 
diff --git a/builtin/branch.c b/builtin/branch.c
index e0aa44c..32a0d11 100644
--- a/builtin/branch.c
+++ b/builtin/branch.c
@@ -26,6 +26,7 @@ static const char * const builtin_branch_usage[] = {
N_("git branch [] [-l] [-f]  []"),
N_("git branch [] [-r] (-d | -D) ..."),
N_("git branch [] (-m | -M) [] "),
+   N_("git branch [] [-r | -a] [--points-at]"),
NULL
 };
 
@@ -652,6 +653,10 @@ int cmd_branch(int argc, const char **argv, const char 
*prefix)
OPT_COLUMN(0, "column", &colopts, N_("list branches in 
columns")),
OPT_CALLBACK(0 , "sort", sorting_tail, N_("key"),
 N_("field name to sort on"), 
&parse_opt_ref_sorting),
+   {
+   OPTION_CALLBACK, 0, "points-at", &filter.points_at, 
N_("object"),
+   N_("print only branches of the object"), 0, 
parse_opt_object_name
+   },
OPT_END(),
};
 
@@ -680,7 +685,7 @@ int cmd_branch(int argc, const char **argv, const char 
*prefix)
if (!delete && !rename && !edit_description && !new_upstream && 
!unset_upstream && argc == 0)
list = 1;
 
-   if (filter.with_commit || filter.merge != REF_FILTER_MERGED_NONE)
+   if (filter.with_commit || filter.merge != REF_FILTER_MERGED_NONE || 
filter.points_at.nr)
list = 1;
 
if (!!delete + !!rename + !!new_upstream +
diff --git a/t/t3203-branch-output.sh b/t/t3203-branch-output.sh
index 53d166d..c819f3e 100755
--- a/t/t3203-branch-output.sh
+++ b/t/t3203-branch-output.sh
@@ -154,4 +154,13 @@ test_expect_success 'git branch `--sort` option' '
test_i18ncmp expect actual
 '
 
+test_expect_success 'git branch --points-at option' '
+   cat >expect <<-\EOF &&
+ master
+ branch-one
+   EOF
+   git branch --points-at=branch-one >actual &&
+   test_cmp expect actual
+'
+
 test_done
-- 
2.5.0

--
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 v3 6/8] branch.c: use 'ref-filter' data structures

2015-08-21 Thread Karthik Nayak
Make 'branch.c' use 'ref-filter' data structures and make changes to
support the new data structures. This is a part of the process of
porting 'branch.c' to use 'ref-filter' APIs.

This is a temporary step before porting 'branch.c' to use 'ref-filter'
completely. As this is a temporary step, most of the code introduced
here will be removed when 'branch.c' is ported over to use
'ref-filter' APIs.

Make 'free_array_item()' of ref-filter.c a non static function. This
is used to free memory allocated to a detached head ref, before we
print other refs.

Mentored-by: Christian Couder 
Mentored-by: Matthieu Moy 
Signed-off-by: Karthik Nayak 
---
 builtin/branch.c | 328 ++-
 ref-filter.c |   2 +-
 ref-filter.h |   9 +-
 3 files changed, 141 insertions(+), 198 deletions(-)

diff --git a/builtin/branch.c b/builtin/branch.c
index 8b9da60..5cb7ef0 100644
--- a/builtin/branch.c
+++ b/builtin/branch.c
@@ -19,6 +19,7 @@
 #include "column.h"
 #include "utf8.h"
 #include "wt-status.h"
+#include "ref-filter.h"
 
 static const char * const builtin_branch_usage[] = {
N_("git branch [] [-r | -a] [--merged | --no-merged]"),
@@ -28,10 +29,6 @@ static const char * const builtin_branch_usage[] = {
NULL
 };
 
-#define REF_LOCAL_BRANCH0x01
-#define REF_REMOTE_BRANCH   0x02
-#define REF_DETACHED_HEAD   0x04
-
 static const char *head;
 static unsigned char head_sha1[20];
 
@@ -53,13 +50,6 @@ enum color_branch {
BRANCH_COLOR_UPSTREAM = 5
 };
 
-static enum merge_filter {
-   NO_FILTER = 0,
-   SHOW_NOT_MERGED,
-   SHOW_MERGED
-} merge_filter;
-static unsigned char merge_filter_ref[20];
-
 static struct string_list output = STRING_LIST_INIT_DUP;
 static unsigned int colopts;
 
@@ -122,7 +112,7 @@ static int branch_merged(int kind, const char *name,
void *reference_name_to_free = NULL;
int merged;
 
-   if (kind == REF_LOCAL_BRANCH) {
+   if (kind == FILTER_REFS_BRANCHES) {
struct branch *branch = branch_get(name);
const char *upstream = branch_get_upstream(branch, NULL);
unsigned char sha1[20];
@@ -200,14 +190,14 @@ static int delete_branches(int argc, const char **argv, 
int force, int kinds,
struct strbuf bname = STRBUF_INIT;
 
switch (kinds) {
-   case REF_REMOTE_BRANCH:
+   case FILTER_REFS_REMOTES:
fmt = "refs/remotes/%s";
/* For subsequent UI messages */
remote_branch = 1;
 
force = 1;
break;
-   case REF_LOCAL_BRANCH:
+   case FILTER_REFS_BRANCHES:
fmt = "refs/heads/%s";
break;
default:
@@ -224,7 +214,7 @@ static int delete_branches(int argc, const char **argv, int 
force, int kinds,
int flags = 0;
 
strbuf_branchname(&bname, argv[i]);
-   if (kinds == REF_LOCAL_BRANCH && !strcmp(head, bname.buf)) {
+   if (kinds == FILTER_REFS_BRANCHES && !strcmp(head, bname.buf)) {
error(_("Cannot delete the branch '%s' "
  "which you are currently on."), bname.buf);
ret = 1;
@@ -280,22 +270,6 @@ static int delete_branches(int argc, const char **argv, 
int force, int kinds,
return(ret);
 }
 
-struct ref_item {
-   char *name;
-   char *dest;
-   unsigned int kind;
-   struct commit *commit;
-   int ignore;
-};
-
-struct ref_list {
-   struct rev_info revs;
-   int index, alloc, verbose, abbrev;
-   struct ref_item *list;
-   struct commit_list *with_commit;
-   int kinds;
-};
-
 static char *resolve_symref(const char *src, const char *prefix)
 {
unsigned char sha1[20];
@@ -310,11 +284,6 @@ static char *resolve_symref(const char *src, const char 
*prefix)
return xstrdup(dst);
 }
 
-struct append_ref_cb {
-   struct ref_list *ref_list;
-   const char **pattern;
-};
-
 static int match_patterns(const char **pattern, const char *refname)
 {
if (!*pattern)
@@ -327,11 +296,29 @@ static int match_patterns(const char **pattern, const 
char *refname)
return 0;
 }
 
+/*
+ * Allocate memory for a new ref_array_item and insert that into the
+ * given ref_array. Doesn't take the objectname unlike
+ * new_ref_array_item(). This is a temporary function which will be
+ * removed when we port branch.c to use ref-filter APIs.
+ */
+static struct ref_array_item *ref_array_append(struct ref_array *array, const 
char *refname)
+{
+   size_t len = strlen(refname);
+   struct ref_array_item *ref = xcalloc(1, sizeof(struct ref_array_item) + 
len + 1);
+   memcpy(ref->refname, refname, len);
+   ref->refname[len] = '\0';
+   REALLOC_ARRAY(array->items, array->nr + 1);
+   array->items[array->nr++] = ref;
+   return ref;
+}
+
 static int append_ref(const char *refname, const struct object_id *oid, int 
flags

[PATCH v3 3/8] branch: roll show_detached HEAD into regular ref_list

2015-08-21 Thread Karthik Nayak
Remove show_detached() and make detached HEAD to be rolled into
regular ref_list by adding REF_DETACHED_HEAD as a kind of branch and
supporting the same in append_ref(). This eliminates the need for an
extra function and helps in easier porting of branch.c to use
ref-filter APIs.

Before show_detached() used to check if the HEAD branch satisfies the
'--contains' option, now that is taken care by append_ref().

Based-on-patch-by: Jeff King 
Mentored-by: Christian Couder 
Mentored-by: Matthieu Moy 
Signed-off-by: Karthik Nayak 
---
 builtin/branch.c | 68 +---
 1 file changed, 40 insertions(+), 28 deletions(-)

diff --git a/builtin/branch.c b/builtin/branch.c
index 193296a..6ba7a3f 100644
--- a/builtin/branch.c
+++ b/builtin/branch.c
@@ -30,6 +30,7 @@ static const char * const builtin_branch_usage[] = {
 
 #define REF_LOCAL_BRANCH0x01
 #define REF_REMOTE_BRANCH   0x02
+#define REF_DETACHED_HEAD   0x04
 
 static const char *head;
 static unsigned char head_sha1[20];
@@ -352,8 +353,12 @@ static int append_ref(const char *refname, const struct 
object_id *oid, int flag
break;
}
}
-   if (ARRAY_SIZE(ref_kind) <= i)
-   return 0;
+   if (ARRAY_SIZE(ref_kind) <= i) {
+   if (!strcmp(refname, "HEAD"))
+   kind = REF_DETACHED_HEAD;
+   else
+   return 0;
+   }
 
/* Don't add types the caller doesn't want */
if ((kind & ref_list->kinds) == 0)
@@ -535,6 +540,8 @@ static void print_ref_item(struct ref_item *item, int 
maxwidth, int verbose,
int color;
struct strbuf out = STRBUF_INIT, name = STRBUF_INIT;
const char *prefix = "";
+   const char *desc = item->name;
+   char *to_free = NULL;
 
if (item->ignore)
return;
@@ -547,6 +554,10 @@ static void print_ref_item(struct ref_item *item, int 
maxwidth, int verbose,
color = BRANCH_COLOR_REMOTE;
prefix = remote_prefix;
break;
+   case REF_DETACHED_HEAD:
+   color = BRANCH_COLOR_CURRENT;
+   desc = to_free = get_head_description();
+   break;
default:
color = BRANCH_COLOR_PLAIN;
break;
@@ -558,7 +569,7 @@ static void print_ref_item(struct ref_item *item, int 
maxwidth, int verbose,
color = BRANCH_COLOR_CURRENT;
}
 
-   strbuf_addf(&name, "%s%s", prefix, item->name);
+   strbuf_addf(&name, "%s%s", prefix, desc);
if (verbose) {
int utf8_compensation = strlen(name.buf) - 
utf8_strwidth(name.buf);
strbuf_addf(&out, "%c %s%-*s%s", c, branch_get_color(color),
@@ -581,6 +592,7 @@ static void print_ref_item(struct ref_item *item, int 
maxwidth, int verbose,
}
strbuf_release(&name);
strbuf_release(&out);
+   free(to_free);
 }
 
 static int calc_maxwidth(struct ref_list *refs, int remote_bonus)
@@ -601,25 +613,9 @@ static int calc_maxwidth(struct ref_list *refs, int 
remote_bonus)
return max;
 }
 
-static void show_detached(struct ref_list *ref_list, int maxwidth)
-{
-   struct commit *head_commit = lookup_commit_reference_gently(head_sha1, 
1);
-
-   if (head_commit && is_descendant_of(head_commit, 
ref_list->with_commit)) {
-   struct ref_item item;
-   item.name = get_head_description();
-   item.kind = REF_LOCAL_BRANCH;
-   item.dest = NULL;
-   item.commit = head_commit;
-   item.ignore = 0;
-   print_ref_item(&item, maxwidth, ref_list->verbose, 
ref_list->abbrev, 1, "");
-   free(item.name);
-   }
-}
-
 static int print_ref_list(int kinds, int detached, int verbose, int abbrev, 
struct commit_list *with_commit, const char **pattern)
 {
-   int i;
+   int i, index;
struct append_ref_cb cb;
struct ref_list ref_list;
int maxwidth = 0;
@@ -643,7 +639,14 @@ static int print_ref_list(int kinds, int detached, int 
verbose, int abbrev, stru
cb.ref_list = &ref_list;
cb.pattern = pattern;
cb.ret = 0;
+   /*
+* First we obtain all regular branch refs and if the HEAD is
+* detached then we insert that ref to the end of the ref_fist
+* so that it can be printed and removed first.
+*/
for_each_rawref(append_ref, &cb);
+   if (detached)
+   head_ref(append_ref, &cb);
/*
 * The following implementation is currently duplicated in ref-filter. 
It
 * will eventually be removed when we port branch.c to use ref-filter 
APIs.
@@ -679,15 +682,20 @@ static int print_ref_list(int kinds, int detached, int 
verbose, int abbrev, stru
if (verbose)
maxwidth = calc_maxwidth(&ref_list, strlen(remote_prefix));
 
-   qsort(ref_list.list, ref_list.index

[PATCH v3 4/8] branch: move 'current' check down to the presentation layer

2015-08-21 Thread Karthik Nayak
We check if given ref is the current branch in print_ref_list(). Move
this check to print_ref_item() where it is checked right before
printing.

Based-on-patch-by: Jeff King 
Mentored-by: Christian Couder 
Mentored-by: Matthieu Moy 
Signed-off-by: Karthik Nayak 
---
 builtin/branch.c | 22 +++---
 1 file changed, 11 insertions(+), 11 deletions(-)

diff --git a/builtin/branch.c b/builtin/branch.c
index 6ba7a3f..4d9e4d0 100644
--- a/builtin/branch.c
+++ b/builtin/branch.c
@@ -534,9 +534,10 @@ static char *get_head_description(void)
 }
 
 static void print_ref_item(struct ref_item *item, int maxwidth, int verbose,
-  int abbrev, int current, const char *remote_prefix)
+  int abbrev, int detached, const char *remote_prefix)
 {
char c;
+   int current = 0;
int color;
struct strbuf out = STRBUF_INIT, name = STRBUF_INIT;
const char *prefix = "";
@@ -548,15 +549,18 @@ static void print_ref_item(struct ref_item *item, int 
maxwidth, int verbose,
 
switch (item->kind) {
case REF_LOCAL_BRANCH:
-   color = BRANCH_COLOR_LOCAL;
+   if (!detached && !strcmp(item->name, head))
+   current = 1;
+   else
+   color = BRANCH_COLOR_LOCAL;
break;
case REF_REMOTE_BRANCH:
color = BRANCH_COLOR_REMOTE;
prefix = remote_prefix;
break;
case REF_DETACHED_HEAD:
-   color = BRANCH_COLOR_CURRENT;
desc = to_free = get_head_description();
+   current = 1;
break;
default:
color = BRANCH_COLOR_PLAIN;
@@ -685,21 +689,17 @@ static int print_ref_list(int kinds, int detached, int 
verbose, int abbrev, stru
index = ref_list.index;
 
/* Print detached HEAD before sorting and printing the rest */
-   if (detached && (ref_list.list[index - 1].kind == REF_DETACHED_HEAD) &&
-   !strcmp(ref_list.list[index - 1].name, head)) {
+   if (detached) {
print_ref_item(&ref_list.list[index - 1], maxwidth, verbose, 
abbrev,
-  1, remote_prefix);
+  detached, remote_prefix);
index -= 1;
}
 
qsort(ref_list.list, index, sizeof(struct ref_item), ref_cmp);
 
-   for (i = 0; i < index; i++) {
-   int current = !detached && (ref_list.list[i].kind == 
REF_LOCAL_BRANCH) &&
-   !strcmp(ref_list.list[i].name, head);
+   for (i = 0; i < index; i++)
print_ref_item(&ref_list.list[i], maxwidth, verbose,
-  abbrev, current, remote_prefix);
-   }
+  abbrev, detached, remote_prefix);
 
free_ref_list(&ref_list);
 
-- 
2.5.0

--
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 v3 5/8] branch: drop non-commit error reporting

2015-08-21 Thread Karthik Nayak
Remove the error reporting variable to make the code easier to port
over to using ref-filter APIs. This variable is not required as in
ref-filter we already check for possible errors and report them.

Based-on-patch-by: Jeff King 
Mentored-by: Christian Couder 
Mentored-by: Matthieu Moy 
Signed-off-by: Karthik Nayak 
---
 builtin/branch.c | 18 --
 1 file changed, 4 insertions(+), 14 deletions(-)

diff --git a/builtin/branch.c b/builtin/branch.c
index 4d9e4d0..8b9da60 100644
--- a/builtin/branch.c
+++ b/builtin/branch.c
@@ -313,7 +313,6 @@ static char *resolve_symref(const char *src, const char 
*prefix)
 struct append_ref_cb {
struct ref_list *ref_list;
const char **pattern;
-   int ret;
 };
 
 static int match_patterns(const char **pattern, const char *refname)
@@ -370,10 +369,8 @@ static int append_ref(const char *refname, const struct 
object_id *oid, int flag
commit = NULL;
if (ref_list->verbose || ref_list->with_commit || merge_filter != 
NO_FILTER) {
commit = lookup_commit_reference_gently(oid->hash, 1);
-   if (!commit) {
-   cb->ret = error(_("branch '%s' does not point at a 
commit"), refname);
+   if (!commit)
return 0;
-   }
 
/* Filter with with_commit if specified */
if (!is_descendant_of(commit, ref_list->with_commit))
@@ -617,7 +614,7 @@ static int calc_maxwidth(struct ref_list *refs, int 
remote_bonus)
return max;
 }
 
-static int print_ref_list(int kinds, int detached, int verbose, int abbrev, 
struct commit_list *with_commit, const char **pattern)
+static void print_ref_list(int kinds, int detached, int verbose, int abbrev, 
struct commit_list *with_commit, const char **pattern)
 {
int i, index;
struct append_ref_cb cb;
@@ -642,7 +639,6 @@ static int print_ref_list(int kinds, int detached, int 
verbose, int abbrev, stru
init_revisions(&ref_list.revs, NULL);
cb.ref_list = &ref_list;
cb.pattern = pattern;
-   cb.ret = 0;
/*
 * First we obtain all regular branch refs and if the HEAD is
 * detached then we insert that ref to the end of the ref_fist
@@ -702,11 +698,6 @@ static int print_ref_list(int kinds, int detached, int 
verbose, int abbrev, stru
   abbrev, detached, remote_prefix);
 
free_ref_list(&ref_list);
-
-   if (cb.ret)
-   error(_("some refs could not be read"));
-
-   return cb.ret;
 }
 
 static void rename_branch(const char *oldname, const char *newname, int force)
@@ -922,15 +913,14 @@ int cmd_branch(int argc, const char **argv, const char 
*prefix)
die(_("branch name required"));
return delete_branches(argc, argv, delete > 1, kinds, quiet);
} else if (list) {
-   int ret;
/*  git branch --local also shows HEAD when it is detached */
if (kinds & REF_LOCAL_BRANCH)
kinds |= REF_DETACHED_HEAD;
-   ret = print_ref_list(kinds, detached, verbose, abbrev,
+   print_ref_list(kinds, detached, verbose, abbrev,
 with_commit, argv);
print_columns(&output, colopts, NULL);
string_list_clear(&output, 0);
-   return ret;
+   return 0;
}
else if (edit_description) {
const char *branch_name;
-- 
2.5.0

--
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 v3 2/8] branch: bump get_head_description() to the top

2015-08-21 Thread Karthik Nayak
This is a preperatory patch for 'roll show_detached HEAD into regular
ref_list'. This patch moves get_head_description() to the top so that
it can be used in print_ref_item().

Based-on-patch-by: Jeff King 
Mentored-by: Christian Couder 
Mentored-by: Matthieu Moy 
Signed-off-by: Karthik Nayak 
---
 builtin/branch.c | 62 
 1 file changed, 31 insertions(+), 31 deletions(-)

diff --git a/builtin/branch.c b/builtin/branch.c
index 28a10d6..193296a 100644
--- a/builtin/branch.c
+++ b/builtin/branch.c
@@ -497,6 +497,37 @@ static void add_verbose_info(struct strbuf *out, struct 
ref_item *item,
strbuf_release(&subject);
 }
 
+static char *get_head_description(void)
+{
+   struct strbuf desc = STRBUF_INIT;
+   struct wt_status_state state;
+   memset(&state, 0, sizeof(state));
+   wt_status_get_state(&state, 1);
+   if (state.rebase_in_progress ||
+   state.rebase_interactive_in_progress)
+   strbuf_addf(&desc, _("(no branch, rebasing %s)"),
+   state.branch);
+   else if (state.bisect_in_progress)
+   strbuf_addf(&desc, _("(no branch, bisect started on %s)"),
+   state.branch);
+   else if (state.detached_from) {
+   /* TRANSLATORS: make sure these match _("HEAD detached at ")
+  and _("HEAD detached from ") in wt-status.c */
+   if (state.detached_at)
+   strbuf_addf(&desc, _("(HEAD detached at %s)"),
+   state.detached_from);
+   else
+   strbuf_addf(&desc, _("(HEAD detached from %s)"),
+   state.detached_from);
+   }
+   else
+   strbuf_addstr(&desc, _("(no branch)"));
+   free(state.branch);
+   free(state.onto);
+   free(state.detached_from);
+   return strbuf_detach(&desc, NULL);
+}
+
 static void print_ref_item(struct ref_item *item, int maxwidth, int verbose,
   int abbrev, int current, const char *remote_prefix)
 {
@@ -570,37 +601,6 @@ static int calc_maxwidth(struct ref_list *refs, int 
remote_bonus)
return max;
 }
 
-static char *get_head_description(void)
-{
-   struct strbuf desc = STRBUF_INIT;
-   struct wt_status_state state;
-   memset(&state, 0, sizeof(state));
-   wt_status_get_state(&state, 1);
-   if (state.rebase_in_progress ||
-   state.rebase_interactive_in_progress)
-   strbuf_addf(&desc, _("(no branch, rebasing %s)"),
-   state.branch);
-   else if (state.bisect_in_progress)
-   strbuf_addf(&desc, _("(no branch, bisect started on %s)"),
-   state.branch);
-   else if (state.detached_from) {
-   /* TRANSLATORS: make sure these match _("HEAD detached at ")
-  and _("HEAD detached from ") in wt-status.c */
-   if (state.detached_at)
-   strbuf_addf(&desc, _("(HEAD detached at %s)"),
-   state.detached_from);
-   else
-   strbuf_addf(&desc, _("(HEAD detached from %s)"),
-   state.detached_from);
-   }
-   else
-   strbuf_addstr(&desc, _("(no branch)"));
-   free(state.branch);
-   free(state.onto);
-   free(state.detached_from);
-   return strbuf_detach(&desc, NULL);
-}
-
 static void show_detached(struct ref_list *ref_list, int maxwidth)
 {
struct commit *head_commit = lookup_commit_reference_gently(head_sha1, 
1);
-- 
2.5.0

--
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 v3 1/8] branch: refactor width computation

2015-08-21 Thread Karthik Nayak
From: Karthik Nayak 

Remove unnecessary variables from ref_list and ref_item which were
used for width computation. This is to make ref_item similar to
ref-filter's ref_array_item. This will ensure a smooth port of
branch.c to use ref-filter APIs in further patches.

Previously the maxwidth was computed when inserting the refs into the
ref_list. Now, we obtain the entire ref_list and then compute
maxwidth.

Based-on-patch-by: Jeff King 
Mentored-by: Christian Couder 
Mentored-by: Matthieu Moy 
Signed-off-by: Karthik Nayak 
---
 builtin/branch.c | 64 ++--
 1 file changed, 34 insertions(+), 30 deletions(-)

diff --git a/builtin/branch.c b/builtin/branch.c
index 4fc8beb..28a10d6 100644
--- a/builtin/branch.c
+++ b/builtin/branch.c
@@ -282,14 +282,14 @@ static int delete_branches(int argc, const char **argv, 
int force, int kinds,
 struct ref_item {
char *name;
char *dest;
-   unsigned int kind, width;
+   unsigned int kind;
struct commit *commit;
int ignore;
 };
 
 struct ref_list {
struct rev_info revs;
-   int index, alloc, maxwidth, verbose, abbrev;
+   int index, alloc, verbose, abbrev;
struct ref_item *list;
struct commit_list *with_commit;
int kinds;
@@ -386,15 +386,8 @@ static int append_ref(const char *refname, const struct 
object_id *oid, int flag
newitem->name = xstrdup(refname);
newitem->kind = kind;
newitem->commit = commit;
-   newitem->width = utf8_strwidth(refname);
newitem->dest = resolve_symref(orig_refname, prefix);
newitem->ignore = 0;
-   /* adjust for "remotes/" */
-   if (newitem->kind == REF_REMOTE_BRANCH &&
-   ref_list->kinds != REF_REMOTE_BRANCH)
-   newitem->width += 8;
-   if (newitem->width > ref_list->maxwidth)
-   ref_list->maxwidth = newitem->width;
 
return 0;
 }
@@ -505,11 +498,12 @@ static void add_verbose_info(struct strbuf *out, struct 
ref_item *item,
 }
 
 static void print_ref_item(struct ref_item *item, int maxwidth, int verbose,
-  int abbrev, int current, char *prefix)
+  int abbrev, int current, const char *remote_prefix)
 {
char c;
int color;
struct strbuf out = STRBUF_INIT, name = STRBUF_INIT;
+   const char *prefix = "";
 
if (item->ignore)
return;
@@ -520,6 +514,7 @@ static void print_ref_item(struct ref_item *item, int 
maxwidth, int verbose,
break;
case REF_REMOTE_BRANCH:
color = BRANCH_COLOR_REMOTE;
+   prefix = remote_prefix;
break;
default:
color = BRANCH_COLOR_PLAIN;
@@ -557,16 +552,22 @@ static void print_ref_item(struct ref_item *item, int 
maxwidth, int verbose,
strbuf_release(&out);
 }
 
-static int calc_maxwidth(struct ref_list *refs)
+static int calc_maxwidth(struct ref_list *refs, int remote_bonus)
 {
-   int i, w = 0;
+   int i, max = 0;
for (i = 0; i < refs->index; i++) {
-   if (refs->list[i].ignore)
+   struct ref_item *it = &refs->list[i];
+   int w;
+
+   if (it->ignore)
continue;
-   if (refs->list[i].width > w)
-   w = refs->list[i].width;
+   w = utf8_strwidth(it->name);
+   if (it->kind == REF_REMOTE_BRANCH)
+   w += remote_bonus;
+   if (w > max)
+   max = w;
}
-   return w;
+   return max;
 }
 
 static char *get_head_description(void)
@@ -600,21 +601,18 @@ static char *get_head_description(void)
return strbuf_detach(&desc, NULL);
 }
 
-static void show_detached(struct ref_list *ref_list)
+static void show_detached(struct ref_list *ref_list, int maxwidth)
 {
struct commit *head_commit = lookup_commit_reference_gently(head_sha1, 
1);
 
if (head_commit && is_descendant_of(head_commit, 
ref_list->with_commit)) {
struct ref_item item;
item.name = get_head_description();
-   item.width = utf8_strwidth(item.name);
item.kind = REF_LOCAL_BRANCH;
item.dest = NULL;
item.commit = head_commit;
item.ignore = 0;
-   if (item.width > ref_list->maxwidth)
-   ref_list->maxwidth = item.width;
-   print_ref_item(&item, ref_list->maxwidth, ref_list->verbose, 
ref_list->abbrev, 1, "");
+   print_ref_item(&item, maxwidth, ref_list->verbose, 
ref_list->abbrev, 1, "");
free(item.name);
}
 }
@@ -624,6 +622,16 @@ static int print_ref_list(int kinds, int detached, int 
verbose, int abbrev, stru
int i;
struct append_ref_cb cb;
struct ref_list ref_list;
+   int maxwidth = 0;
+   const char *remote_

[PATCH v3 0/8] port the filtering part of ref-filter to branch.c

2015-08-21 Thread Karthik Nayak
This is a follow up to porting tag.c to use ref-fitler APIs.

v2 of this patch series can be found here:
http://thread.gmane.org/gmane.comp.version-control.git/276147

Changes made in this series:
* Improve comment in 3/8 and fix grammar in 5/8.
* Fix the test in t1430 to check stderr for the broken ref warning.
* Instead of showing the detached head, reducing the no of array elements
and displaying all of the other refs and then free'ing all of the refs. We
now free the detached head ref immediately after displaying so we don't have
to bother about decrementing and incrementing the no of array elements.
* 

Karthik Nayak (8):
  branch: refactor width computation
  branch: bump get_head_description() to the top
  branch: roll show_detached HEAD into regular ref_list
  branch: move 'current' check down to the presentation layer
  branch: drop non-commit error reporting
  branch.c: use 'ref-filter' data structures
  branch.c: use 'ref-filter' APIs
  branch: add '--points-at' option

 Documentation/git-branch.txt |  13 +-
 builtin/branch.c | 506 +--
 ref-filter.c |   4 +-
 ref-filter.h |   8 +-
 t/t1430-bad-ref-name.sh  |   2 +-
 t/t3203-branch-output.sh |  20 ++
 6 files changed, 197 insertions(+), 356 deletions(-)

Interdiff:

diff --git a/builtin/branch.c b/builtin/branch.c
index dd2fdbe..32a0d11 100644
--- a/builtin/branch.c
+++ b/builtin/branch.c
@@ -475,7 +475,7 @@ static int calc_maxwidth(struct ref_array *refs, int 
remote_bonus)
 
 static void print_ref_list(struct ref_filter *filter, struct ref_sorting 
*sorting)
 {
-   int i, index;
+   int i;
struct ref_array array;
int maxwidth = 0;
const char *remote_prefix = "";
@@ -493,17 +493,16 @@ static void print_ref_list(struct ref_filter *filter, 
struct ref_sorting *sortin
memset(&array, 0, sizeof(array));
 
verify_ref_format("%(refname)%(symref)");
-   filter_refs(&array, filter, filter->kind);
+   filter_refs(&array, filter, filter->kind | FILTER_REFS_INCLUDE_BROKEN);
 
if (filter->verbose)
maxwidth = calc_maxwidth(&array, strlen(remote_prefix));
 
-   index = array.nr;
-
/* Print detached HEAD before sorting and printing the rest */
if (filter->kind & FILTER_REFS_DETACHED_HEAD) {
-   format_and_print_ref_item(array.items[index - 1], maxwidth, 
filter, remote_prefix);
-   array.nr -= 1;
+   format_and_print_ref_item(array.items[array.nr - 1], maxwidth, 
filter, remote_prefix);
+   free_array_item(array.items[array.nr - 1]);
+   array.nr--;
}
 
if (!sorting) {
@@ -517,7 +516,6 @@ static void print_ref_list(struct ref_filter *filter, 
struct ref_sorting *sortin
for (i = 0; i < array.nr; i++)
format_and_print_ref_item(array.items[i], maxwidth, filter, 
remote_prefix);
 
-   array.nr = index;
ref_array_clear(&array);
 }
 
diff --git a/ref-filter.c b/ref-filter.c
index 112feaa..3cd0c00 100644
--- a/ref-filter.c
+++ b/ref-filter.c
@@ -1251,7 +1251,7 @@ static int ref_filter_handler(const char *refname, const 
struct object_id *oid,
 }
 
 /*  Free memory allocated for a ref_array_item */
-static void free_array_item(struct ref_array_item *item)
+void free_array_item(struct ref_array_item *item)
 {
free((char *)item->symref);
free(item);
diff --git a/ref-filter.h b/ref-filter.h
index 3e29e5d..3e25d84 100644
--- a/ref-filter.h
+++ b/ref-filter.h
@@ -89,6 +89,8 @@ struct ref_filter_cbdata {
  * filtered refs in the ref_array structure.
  */
 int filter_refs(struct ref_array *array, struct ref_filter *filter, unsigned 
int type);
+/*  Clear memory allocated to a ref_array_item */
+void free_array_item(struct ref_array_item *item);
 /*  Clear all memory allocated to ref_array */
 void ref_array_clear(struct ref_array *array);
 /*  Parse format string and sort specifiers */
diff --git a/t/t1430-bad-ref-name.sh b/t/t1430-bad-ref-name.sh
index dcf2931..db3627e 100755
--- a/t/t1430-bad-ref-name.sh
+++ b/t/t1430-bad-ref-name.sh
@@ -38,11 +38,11 @@ test_expect_success 'fast-import: fail on invalid branch 
name "bad[branch]name"'
test_must_fail git fast-import output &&
-   grep -e "broken\.\.\.ref" output
+test_expect_success 'git branch shows badly named ref as warning' '
+   cp .git/refs/heads/master .git/refs/heads/broken...ref &&
+   test_when_finished "rm -f .git/refs/heads/broken...ref" &&
+   git branch 2>output &&
+   grep -e "broken\.\.\.ref" output
 '
 
 test_expect_success 'branch -d can delete badly named ref' '
diff --git a/t/t3203-branch-output.sh b/t/t3203-branch-output.sh
index 1deb7cb..c819f3e 100755
--- a/t/t3203-branch-output.sh
+++ b/t/t3203-branch-output.sh
@@ -144,21 +144,21 @@ EOF
 '
 
 test_expect_success 'git branch `--sort` option' '
-   cat >expect 

[PATCH v13 11/12] tag.c: implement '--format' option

2015-08-21 Thread Karthik Nayak
Implement the '--format' option provided by 'ref-filter'.
This lets the user list tags as per desired format similar
to the implementation in 'git for-each-ref'.

Add tests and documentation for the same.

Mentored-by: Christian Couder 
Mentored-by: Matthieu Moy 
Signed-off-by: Karthik Nayak 
---
 Documentation/git-tag.txt |  8 +++-
 builtin/tag.c | 19 +++
 t/t7004-tag.sh| 12 
 3 files changed, 30 insertions(+), 9 deletions(-)

diff --git a/Documentation/git-tag.txt b/Documentation/git-tag.txt
index 3ac4a96..0c7f4e6 100644
--- a/Documentation/git-tag.txt
+++ b/Documentation/git-tag.txt
@@ -13,7 +13,8 @@ SYNOPSIS
 [ | ]
 'git tag' -d ...
 'git tag' [-n[]] -l [--contains ] [--points-at ]
-   [--column[=] | --no-column] [--create-reflog] [--sort=] 
[...]
+   [--column[=] | --no-column] [--create-reflog] [--sort=]
+   [--format=] [...]
 'git tag' -v ...
 
 DESCRIPTION
@@ -158,6 +159,11 @@ This option is only applicable when listing tags without 
annotation lines.
The object that the new tag will refer to, usually a commit.
Defaults to HEAD.
 
+::
+   A string that interpolates `%(fieldname)` from the object
+   pointed at by a ref being shown.  The format is the same as
+   that of linkgit:git-for-each-ref[1].  When unspecified,
+   defaults to `%(refname:short)`.
 
 CONFIGURATION
 -
diff --git a/builtin/tag.c b/builtin/tag.c
index 501fc52..4b8d6df 100644
--- a/builtin/tag.c
+++ b/builtin/tag.c
@@ -23,17 +23,16 @@ static const char * const git_tag_usage[] = {
N_("git tag [-a | -s | -u ] [-f] [-m  | -F ] 
 []"),
N_("git tag -d ..."),
N_("git tag -l [-n[]] [--contains ] [--points-at ]"
-   "\n\t\t[...]"),
+   "\n\t\t[--format=] [...]"),
N_("git tag -v ..."),
NULL
 };
 
 static unsigned int colopts;
 
-static int list_tags(struct ref_filter *filter, struct ref_sorting *sorting)
+static int list_tags(struct ref_filter *filter, struct ref_sorting *sorting, 
const char *format)
 {
struct ref_array array;
-   char *format;
int i;
 
memset(&array, 0, sizeof(array));
@@ -41,10 +40,12 @@ static int list_tags(struct ref_filter *filter, struct 
ref_sorting *sorting)
if (filter->lines == -1)
filter->lines = 0;
 
-   if (filter->lines)
-   format = "%(align:16,left)%(refname:short)%(end)";
-   else
-   format = "%(refname:short)";
+   if (!format) {
+   if (filter->lines)
+   format = "%(align:16,left)%(refname:short)%(end)";
+   else
+   format = "%(refname:short)";
+   }
 
verify_ref_format(format);
filter_refs(&array, filter, FILTER_REFS_TAGS);
@@ -327,6 +328,7 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
struct strbuf err = STRBUF_INIT;
struct ref_filter filter;
static struct ref_sorting *sorting = NULL, **sorting_tail = &sorting;
+   const char *format = NULL;
struct option options[] = {
OPT_CMDMODE('l', "list", &cmdmode, N_("list tag names"), 'l'),
{ OPTION_INTEGER, 'n', NULL, &filter.lines, N_("n"),
@@ -359,6 +361,7 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
OPTION_CALLBACK, 0, "points-at", &filter.points_at, 
N_("object"),
N_("print only tags of the object"), 0, 
parse_opt_object_name
},
+   OPT_STRING(  0 , "format", &format, N_("format"), N_("format to 
use for the output")),
OPT_END()
};
 
@@ -399,7 +402,7 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
run_column_filter(colopts, &copts);
}
filter.name_patterns = argv;
-   ret = list_tags(&filter, sorting);
+   ret = list_tags(&filter, sorting, format);
if (column_active(colopts))
stop_column_filter();
return ret;
diff --git a/t/t7004-tag.sh b/t/t7004-tag.sh
index 84153ef..8987fb1 100755
--- a/t/t7004-tag.sh
+++ b/t/t7004-tag.sh
@@ -1519,4 +1519,16 @@ EOF"
test_cmp expect actual
 '
 
+test_expect_success '--format should list tags as per format given' '
+   cat >expect <<-\EOF &&
+   refname : refs/tags/foo1.10
+   refname : refs/tags/foo1.3
+   refname : refs/tags/foo1.6
+   refname : refs/tags/foo1.6-rc1
+   refname : refs/tags/foo1.6-rc2
+   EOF
+   git tag -l --format="refname : %(refname)" "foo*" >actual &&
+   test_cmp expect actual
+'
+
 test_done
-- 
2.5.0

--
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 v13 06/12] ref-filter: support printing N lines from tag annotation

2015-08-21 Thread Karthik Nayak
From: Karthik Nayak 

In 'tag.c' we can print N lines from the annotation of the tag using
the '-n' option. Copy code from 'tag.c' to 'ref-filter' and
modify 'ref-filter' to support printing of N lines from the annotation
of tags.

Mentored-by: Christian Couder 
Mentored-by: Matthieu Moy 
Signed-off-by: Karthik Nayak 
---
 builtin/for-each-ref.c |  2 +-
 builtin/tag.c  |  4 
 ref-filter.c   | 51 +-
 ref-filter.h   | 11 ---
 4 files changed, 63 insertions(+), 5 deletions(-)

diff --git a/builtin/for-each-ref.c b/builtin/for-each-ref.c
index 40f343b..e4a4f8a 100644
--- a/builtin/for-each-ref.c
+++ b/builtin/for-each-ref.c
@@ -74,7 +74,7 @@ int cmd_for_each_ref(int argc, const char **argv, const char 
*prefix)
if (!maxcount || array.nr < maxcount)
maxcount = array.nr;
for (i = 0; i < maxcount; i++)
-   show_ref_array_item(array.items[i], format, quote_style);
+   show_ref_array_item(array.items[i], format, quote_style, 0);
ref_array_clear(&array);
return 0;
 }
diff --git a/builtin/tag.c b/builtin/tag.c
index 471d6b1..0fc7557 100644
--- a/builtin/tag.c
+++ b/builtin/tag.c
@@ -185,6 +185,10 @@ static enum contains_result contains(struct commit 
*candidate,
return contains_test(candidate, want);
 }
 
+/*
+ * Currently duplicated in ref-filter, will eventually be removed as
+ * we port tag.c to use ref-filter APIs.
+ */
 static void show_tag_lines(const struct object_id *oid, int lines)
 {
int i;
diff --git a/ref-filter.c b/ref-filter.c
index d5fae1a..515147b 100644
--- a/ref-filter.c
+++ b/ref-filter.c
@@ -1431,7 +1431,51 @@ static void append_literal(const char *cp, const char 
*ep, struct ref_formatting
}
 }
 
-void show_ref_array_item(struct ref_array_item *info, const char *format, int 
quote_style)
+/*
+ * If 'lines' is greater than 0, print that many lines from the given
+ * object_id 'oid'.
+ */
+static void show_tag_lines(const struct object_id *oid, int lines)
+{
+   int i;
+   unsigned long size;
+   enum object_type type;
+   char *buf, *sp, *eol;
+   size_t len;
+
+   buf = read_sha1_file(oid->hash, &type, &size);
+   if (!buf)
+   die_errno("unable to read object %s", oid_to_hex(oid));
+   if (type != OBJ_COMMIT && type != OBJ_TAG)
+   goto free_return;
+   if (!size)
+   die("an empty %s object %s?",
+   typename(type), oid_to_hex(oid));
+
+   /* skip header */
+   sp = strstr(buf, "\n\n");
+   if (!sp)
+   goto free_return;
+
+   /* only take up to "lines" lines, and strip the signature from a tag */
+   if (type == OBJ_TAG)
+   size = parse_signature(buf, size);
+   for (i = 0, sp += 2; i < lines && sp < buf + size; i++) {
+   if (i)
+   printf("\n");
+   eol = memchr(sp, '\n', size - (sp - buf));
+   len = eol ? eol - sp : size - (sp - buf);
+   fwrite(sp, len, 1, stdout);
+   if (!eol)
+   break;
+   sp = eol + 1;
+   }
+free_return:
+   free(buf);
+}
+
+void show_ref_array_item(struct ref_array_item *info, const char *format,
+int quote_style, unsigned int lines)
 {
const char *cp, *sp, *ep;
struct strbuf *final_buf;
@@ -1478,6 +1522,11 @@ void show_ref_array_item(struct ref_array_item *info, 
const char *format, int qu
final_buf = &state.stack->output;
fwrite(final_buf->buf, 1, final_buf->len, stdout);
pop_stack_element(&state.stack);
+   if (lines > 0) {
+   struct object_id oid;
+   hashcpy(oid.hash, info->objectname);
+   show_tag_lines(&oid, lines);
+   }
putchar('\n');
 }
 
diff --git a/ref-filter.h b/ref-filter.h
index 99f081b..c599ea2 100644
--- a/ref-filter.h
+++ b/ref-filter.h
@@ -58,7 +58,8 @@ struct ref_filter {
struct commit *merge_commit;
 
unsigned int with_commit_tag_algo : 1;
-   unsigned int kind;
+   unsigned int kind,
+   lines;
 };
 
 struct ref_filter_cbdata {
@@ -90,8 +91,12 @@ int parse_ref_filter_atom(const char *atom, const char *ep);
 int verify_ref_format(const char *format);
 /*  Sort the given ref_array as per the ref_sorting provided */
 void ref_array_sort(struct ref_sorting *sort, struct ref_array *array);
-/*  Print the ref using the given format and quote_style */
-void show_ref_array_item(struct ref_array_item *info, const char *format, int 
quote_style);
+/*
+ * Print the ref using the given format and quote_style. If 'lines' > 0,
+ * print that many lines of the the given ref.
+ */
+void show_ref_array_item(struct ref_array_item *info, const char *format,
+int quote_style, unsigned int lines);
 /*  Callback function for parsing the sort option */
 int 

[PATCH v13 04/12] ref-filter: implement an `align` atom

2015-08-21 Thread Karthik Nayak
Implement an `align` atom which left-, middle-, or right-aligns the
content between %(align:..) and %(end).

It is followed by `:,`, where the `` is
either left, right or middle and `` is the size of the area
into which the content will be placed. If the content between
%(align:) and %(end) is more than the width then no alignment is
performed. e.g. to align a refname atom to the middle with a total
width of 40 we can do: --format="%(align:middle,40)%(refname)%(end)".

We now have a `handler()` for each atom_value which will be called
when that atom_value is being parsed, and similarly an `at_end`
function for each element of the stack which is to be called when the
`end` atom is encountered. Using this we implement the `align` atom
which aligns the given strbuf by calling `strbuf_utf8_align()` from
utf8.c.

Extract perform_quote_formatting() from append_atom(). Given a string
a quote_value and a strbuf, perform_quote_formatting() formats the
string based on the quote_value and stores it into the strbuf.

Ensure that quote formatting is performed on the whole of
%(align)...%(end) rather than individual atoms. We do this by skipping
individual quote formatting for atoms whenever the stack has more than
one element, and performing formatting for the entire stack element
when the `%(end)` atoms is encountered.

Add documentation and tests for the same.

Mentored-by: Christian Couder 
Mentored-by: Matthieu Moy 
Signed-off-by: Karthik Nayak 
---
 Documentation/git-for-each-ref.txt |   9 +++
 ref-filter.c   | 124 ++---
 t/t6302-for-each-ref-filter.sh |  69 +
 3 files changed, 192 insertions(+), 10 deletions(-)

diff --git a/Documentation/git-for-each-ref.txt 
b/Documentation/git-for-each-ref.txt
index e49d578..943975d 100644
--- a/Documentation/git-for-each-ref.txt
+++ b/Documentation/git-for-each-ref.txt
@@ -127,6 +127,15 @@ color::
Change output color.  Followed by `:`, where names
are described in `color.branch.*`.
 
+align::
+   Left-, middle-, or right-align the content between %(align:..)
+   and %(end). Followed by `:,`, where the
+   `` is either left, right or middle and `` is
+   the total length of the content with alignment. If the
+   contents length is more than the width then no alignment is
+   performed. If used with '--quote' everything in between %(align:..)
+   and %(end) is quoted.
+
 In addition to the above, for commit and tag objects, the header
 field names (`tree`, `parent`, `object`, `type`, and `tag`) can
 be used to specify the value in the header field.
diff --git a/ref-filter.c b/ref-filter.c
index d0d8df0..ffec10a 100644
--- a/ref-filter.c
+++ b/ref-filter.c
@@ -10,6 +10,7 @@
 #include "quote.h"
 #include "ref-filter.h"
 #include "revision.h"
+#include "utf8.h"
 
 typedef enum { FIELD_STR, FIELD_ULONG, FIELD_TIME } cmp_type;
 
@@ -53,6 +54,13 @@ static struct {
{ "flag" },
{ "HEAD" },
{ "color" },
+   { "align" },
+   { "end" },
+};
+
+struct align {
+   align_type position;
+   unsigned int width;
 };
 
 #define REF_FORMATTING_STATE_INIT  { 0, NULL }
@@ -60,6 +68,8 @@ static struct {
 struct ref_formatting_stack {
struct ref_formatting_stack *prev;
struct strbuf output;
+   void (*at_end)(struct ref_formatting_stack *stack);
+   void *cb_data;
 };
 
 struct ref_formatting_state {
@@ -69,6 +79,8 @@ struct ref_formatting_state {
 
 struct atom_value {
const char *s;
+   struct align *align;
+   void (*handler)(struct atom_value *atomv, struct ref_formatting_state 
*state);
unsigned long ul; /* used for sorting when not FIELD_STR */
 };
 
@@ -632,6 +644,51 @@ static inline char *copy_advance(char *dst, const char 
*src)
return dst;
 }
 
+static void align_handler(struct ref_formatting_stack *stack)
+{
+   struct align *align = (struct align *)stack->cb_data;
+   struct strbuf s = STRBUF_INIT;
+
+   strbuf_utf8_align(&s, align->position, align->width, stack->output.buf);
+   strbuf_swap(&stack->output, &s);
+   strbuf_release(&s);
+   free(align);
+}
+
+static void align_atom_handler(struct atom_value *atomv, struct 
ref_formatting_state *state)
+{
+   struct ref_formatting_stack *new;
+
+   push_new_stack_element(&state->stack);
+   new = state->stack;
+   new->at_end = align_handler;
+   new->cb_data = atomv->align;
+}
+
+static void perform_quote_formatting(struct strbuf *s, const char *str, int 
quote_style);
+
+static void end_atom_handler(struct atom_value *atomv, struct 
ref_formatting_state *state)
+{
+   struct ref_formatting_stack *current = state->stack;
+   struct strbuf s = STRBUF_INIT;
+
+   if (!current->at_end)
+   die(_("format: `end` atom used without a supporting atom"));
+   current->at_end(current);
+   /*
+* Whenever we have more than one stack element that means we
+

[PATCH v13 03/12] utf8: add function to align a string into given strbuf

2015-08-21 Thread Karthik Nayak
Add strbuf_utf8_align() which will align a given string into a strbuf
as per given align_type and width. If the width is greater than the
string length then no alignment is performed.

Helped-by: Eric Sunshine 
Mentored-by: Christian Couder 
Mentored-by: Matthieu Moy 
Signed-off-by: Karthik Nayak 
---
 utf8.c | 21 +
 utf8.h | 15 +++
 2 files changed, 36 insertions(+)

diff --git a/utf8.c b/utf8.c
index 28e6d76..00e10c8 100644
--- a/utf8.c
+++ b/utf8.c
@@ -644,3 +644,24 @@ int skip_utf8_bom(char **text, size_t len)
*text += strlen(utf8_bom);
return 1;
 }
+
+void strbuf_utf8_align(struct strbuf *buf, align_type position, unsigned int 
width,
+  const char *s)
+{
+   int slen = strlen(s);
+   int display_len = utf8_strnwidth(s, slen, 0);
+   int utf8_compensation = slen - display_len;
+
+   if (display_len >= width) {
+   strbuf_addstr(buf, s);
+   return;
+   }
+
+   if (position == ALIGN_LEFT)
+   strbuf_addf(buf, "%-*s", width + utf8_compensation, s);
+   else if (position == ALIGN_MIDDLE) {
+   int left = (width - display_len) / 2;
+   strbuf_addf(buf, "%*s%-*s", left, "", width - left + 
utf8_compensation, s);
+   } else if (position == ALIGN_RIGHT)
+   strbuf_addf(buf, "%*s", width + utf8_compensation, s);
+}
diff --git a/utf8.h b/utf8.h
index 5a9e94b..7930b44 100644
--- a/utf8.h
+++ b/utf8.h
@@ -55,4 +55,19 @@ int mbs_chrlen(const char **text, size_t *remainder_p, const 
char *encoding);
  */
 int is_hfs_dotgit(const char *path);
 
+typedef enum {
+   ALIGN_LEFT,
+   ALIGN_MIDDLE,
+   ALIGN_RIGHT
+} align_type;
+
+/*
+ * Align the string given and store it into a strbuf as per the
+ * 'position' and 'width'. If the given string length is larger than
+ * 'width' than then the input string is not truncated and no
+ * alignment is done.
+ */
+void strbuf_utf8_align(struct strbuf *buf, align_type position, unsigned int 
width,
+  const char *s);
+
 #endif
-- 
2.5.0

--
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 v13 00/12] port tag.c to use ref-filter APIs

2015-08-21 Thread Karthik Nayak
Part of my GSoC project to port tag.c to use ref-filter APIs. This is
a follow up to porting for-each-ref to use ref-filter APIs.

Version 12 can be found here:
thread.gmane.org/gmane.comp.version-control.git/276133

Changes since v12:
* %(align)...%(end) now quote formats everything in between the atoms
even if they are string literals. 
* Changet the structure of ref_formatting_state to hold ref_formatting_stack
as the stack and quote_value, this ensures that we do not need to copy the 
quote_value to each element of the stack.
* While checking for %(align) atom, use strbuf_split_str().
* In tag.c support usage of --format with -n.

Karthik Nayak (12):
  ref-filter: move `struct atom_value` to ref-filter.c
  ref-filter: introduce ref_formatting_state and ref_formatting_stack
  utf8: add function to align a string into given strbuf
  ref-filter: implement an `align` atom
  ref-filter: add option to filter out tags, branches and remotes
  ref-filter: support printing N lines from tag annotation
  ref-filter: add support to sort by version
  ref-filter: add option to match literal pattern
  tag.c: use 'ref-filter' data structures
  tag.c: use 'ref-filter' APIs
  tag.c: implement '--format' option
  tag.c: implement '--merged' and '--no-merged' options

 Documentation/git-for-each-ref.txt |  12 ++
 Documentation/git-tag.txt  |  27 ++-
 builtin/for-each-ref.c |   3 +-
 builtin/tag.c  | 365 +++--
 ref-filter.c   | 350 +++
 ref-filter.h   |  32 +++-
 refs.c |   9 +
 refs.h |   1 +
 t/t6302-for-each-ref-filter.sh | 105 +++
 t/t7004-tag.sh |  47 -
 utf8.c |  21 +++
 utf8.h |  15 ++
 12 files changed, 626 insertions(+), 361 deletions(-)


Interdiff:

diff --git a/Documentation/git-for-each-ref.txt 
b/Documentation/git-for-each-ref.txt
index 1997657..06d468e 100644
--- a/Documentation/git-for-each-ref.txt
+++ b/Documentation/git-for-each-ref.txt
@@ -133,7 +133,8 @@ align::
`` is either left, right or middle and `` is
the total length of the content with alignment. If the
contents length is more than the width then no alignment is
-   performed.
+   performed. If used with '--quote' everything in between %(align:..)
+   and %(end) is quoted.
 
 In addition to the above, for commit and tag objects, the header
 field names (`tree`, `parent`, `object`, `type`, and `tag`) can
diff --git a/Documentation/git-tag.txt b/Documentation/git-tag.txt
index c2785d9..3803bf7 100644
--- a/Documentation/git-tag.txt
+++ b/Documentation/git-tag.txt
@@ -161,22 +161,15 @@ This option is only applicable when listing tags without 
annotation lines.
 
 ::
A string that interpolates `%(fieldname)` from the object
-   pointed at by a ref being shown.  If `fieldname` is prefixed
-   with an asterisk (`*`) and the ref points at a tag object, the
-   value for the field in the object tag refers is used.  When
-   unspecified, defaults to `%(refname:short)`.  It also
-   interpolates `%%` to `%`, and `%xx` where `xx` are hex digits
-   interpolates to character with hex code `xx`; for example
-   `%00` interpolates to `\0` (NUL), `%09` to `\t` (TAB) and
-   `%0a` to `\n` (LF).  The fields are same as those in `git
-   for-each-ref`.
+   pointed at by a ref being shown.  The format is the same as
+   that of linkgit:git-for-each-ref[1].  When unspecified,
+   defaults to `%(refname:short)`.
 
 --[no-]merged []::
Only list tags whose tips are reachable, or not reachable
if '--no-merged' is used, from the specified commit ('HEAD'
if not specified).
 
-
 CONFIGURATION
 -
 By default, 'git tag' in sign-with-default mode (-s) will use your
diff --git a/ref-filter.c b/ref-filter.c
index 665221b..f8b8fb7 100644
--- a/ref-filter.c
+++ b/ref-filter.c
@@ -65,18 +65,24 @@ struct align {
unsigned int width;
 };
 
-struct ref_formatting_state {
-   struct ref_formatting_state *prev;
+#define REF_FORMATTING_STATE_INIT  { 0, NULL }
+
+struct ref_formatting_stack {
+   struct ref_formatting_stack *prev;
struct strbuf output;
-   void (*at_end)(struct ref_formatting_state *state);
+   void (*at_end)(struct ref_formatting_stack *stack);
void *cb_data;
+};
+
+struct ref_formatting_state {
int quote_style;
+   struct ref_formatting_stack *stack;
 };
 
 struct atom_value {
const char *s;
struct align *align;
-   void (*handler)(struct atom_value *atomv, struct ref_formatting_state 
**state);
+   void (*handler)(struct atom_value *atomv, struct ref_formatting_state 
*state);
unsigned long ul; /* used for sorting when not FIELD_STR */
 };
 
@@ -149,19 +155,19 @@ int parse_re

[PATCH v13 02/12] ref-filter: introduce ref_formatting_state and ref_formatting_stack

2015-08-21 Thread Karthik Nayak
Introduce ref_formatting_state which will hold the formatted output
strbuf instead of directly printing to stdout. This will help us in
creating modifier atoms which modify the format specified before
printing to stdout.

Implement a stack machinery for ref_formatting_state, this allows us
to push and pop elements onto the stack. Whenever we pop an element
from the stack, the strbuf from that element is appended to the strbuf
of the next element on the stack, this will allow us to support
nesting of modifier atoms.

Rename some functions to reflect the changes made:
print_value() -> append_atom()
emit()-> append_literal()

Mentored-by: Christian Couder 
Mentored-by: Matthieu Moy 
Signed-off-by: Karthik Nayak 
---
 ref-filter.c | 78 +---
 1 file changed, 59 insertions(+), 19 deletions(-)

diff --git a/ref-filter.c b/ref-filter.c
index e53c77e..d0d8df0 100644
--- a/ref-filter.c
+++ b/ref-filter.c
@@ -55,6 +55,18 @@ static struct {
{ "color" },
 };
 
+#define REF_FORMATTING_STATE_INIT  { 0, NULL }
+
+struct ref_formatting_stack {
+   struct ref_formatting_stack *prev;
+   struct strbuf output;
+};
+
+struct ref_formatting_state {
+   int quote_style;
+   struct ref_formatting_stack *stack;
+};
+
 struct atom_value {
const char *s;
unsigned long ul; /* used for sorting when not FIELD_STR */
@@ -129,6 +141,27 @@ int parse_ref_filter_atom(const char *atom, const char *ep)
return at;
 }
 
+static void push_new_stack_element(struct ref_formatting_stack **stack)
+{
+   struct ref_formatting_stack *s = xcalloc(1, sizeof(struct 
ref_formatting_stack));
+
+   strbuf_init(&s->output, 0);
+   s->prev = *stack;
+   *stack = s;
+}
+
+static void pop_stack_element(struct ref_formatting_stack **stack)
+{
+   struct ref_formatting_stack *current = *stack;
+   struct ref_formatting_stack *prev = current->prev;
+
+   if (prev)
+   strbuf_addbuf(&prev->output, ¤t->output);
+   strbuf_release(¤t->output);
+   free(current);
+   *stack = prev;
+}
+
 /*
  * In a format string, find the next occurrence of %(atom).
  */
@@ -1195,30 +1228,27 @@ void ref_array_sort(struct ref_sorting *sorting, struct 
ref_array *array)
qsort(array->items, array->nr, sizeof(struct ref_array_item *), 
compare_refs);
 }
 
-static void print_value(struct atom_value *v, int quote_style)
+static void append_atom(struct atom_value *v, struct ref_formatting_state 
*state)
 {
-   struct strbuf sb = STRBUF_INIT;
-   switch (quote_style) {
+   struct strbuf *s = &state->stack->output;
+
+   switch (state->quote_style) {
case QUOTE_NONE:
-   fputs(v->s, stdout);
+   strbuf_addstr(s, v->s);
break;
case QUOTE_SHELL:
-   sq_quote_buf(&sb, v->s);
+   sq_quote_buf(s, v->s);
break;
case QUOTE_PERL:
-   perl_quote_buf(&sb, v->s);
+   perl_quote_buf(s, v->s);
break;
case QUOTE_PYTHON:
-   python_quote_buf(&sb, v->s);
+   python_quote_buf(s, v->s);
break;
case QUOTE_TCL:
-   tcl_quote_buf(&sb, v->s);
+   tcl_quote_buf(s, v->s);
break;
}
-   if (quote_style != QUOTE_NONE) {
-   fputs(sb.buf, stdout);
-   strbuf_release(&sb);
-   }
 }
 
 static int hex1(char ch)
@@ -1239,8 +1269,10 @@ static int hex2(const char *cp)
return -1;
 }
 
-static void emit(const char *cp, const char *ep)
+static void append_literal(const char *cp, const char *ep, struct 
ref_formatting_state *state)
 {
+   struct strbuf *s = &state->stack->output;
+
while (*cp && (!ep || cp < ep)) {
if (*cp == '%') {
if (cp[1] == '%')
@@ -1248,13 +1280,13 @@ static void emit(const char *cp, const char *ep)
else {
int ch = hex2(cp + 1);
if (0 <= ch) {
-   putchar(ch);
+   strbuf_addch(s, ch);
cp += 3;
continue;
}
}
}
-   putchar(*cp);
+   strbuf_addch(s, *cp);
cp++;
}
 }
@@ -1262,19 +1294,24 @@ static void emit(const char *cp, const char *ep)
 void show_ref_array_item(struct ref_array_item *info, const char *format, int 
quote_style)
 {
const char *cp, *sp, *ep;
+   struct strbuf *final_buf;
+   struct ref_formatting_state state = REF_FORMATTING_STATE_INIT;
+
+   state.quote_style = quote_style;
+   push_new_stack_element(&state.stack);
 
for (cp = format; *cp && (sp = find_next(cp)); cp = ep + 1) {
 

[PATCH v13 08/12] ref-filter: add option to match literal pattern

2015-08-21 Thread Karthik Nayak
From: Karthik Nayak 

Since 'ref-filter' only has an option to match path names add an
option for plain fnmatch pattern-matching.

This is to support the pattern matching options which are used in `git
tag -l` and `git branch -l` where we can match patterns like `git tag
-l foo*` which would match all tags which has a "foo*" pattern.

Mentored-by: Christian Couder 
Mentored-by: Matthieu Moy 
Signed-off-by: Karthik Nayak 
---
 builtin/for-each-ref.c |  1 +
 ref-filter.c   | 40 +---
 ref-filter.h   |  3 ++-
 3 files changed, 40 insertions(+), 4 deletions(-)

diff --git a/builtin/for-each-ref.c b/builtin/for-each-ref.c
index e4a4f8a..3ad6a64 100644
--- a/builtin/for-each-ref.c
+++ b/builtin/for-each-ref.c
@@ -68,6 +68,7 @@ int cmd_for_each_ref(int argc, const char **argv, const char 
*prefix)
git_config(git_default_config, NULL);
 
filter.name_patterns = argv;
+   filter.match_as_path = 1;
filter_refs(&array, &filter, FILTER_REFS_ALL | 
FILTER_REFS_INCLUDE_BROKEN);
ref_array_sort(sorting, &array);
 
diff --git a/ref-filter.c b/ref-filter.c
index b4a7d72..f8b8fb7 100644
--- a/ref-filter.c
+++ b/ref-filter.c
@@ -1055,9 +1055,33 @@ static int commit_contains(struct ref_filter *filter, 
struct commit *commit)
 
 /*
  * Return 1 if the refname matches one of the patterns, otherwise 0.
+ * A pattern can be a literal prefix (e.g. a refname "refs/heads/master"
+ * matches a pattern "refs/heads/mas") or a wildcard (e.g. the same ref
+ * matches "refs/heads/mas*", too).
+ */
+static int match_pattern(const char **patterns, const char *refname)
+{
+   /*
+* When no '--format' option is given we need to skip the prefix
+* for matching refs of tags and branches.
+*/
+   (void)(skip_prefix(refname, "refs/tags/", &refname) ||
+  skip_prefix(refname, "refs/heads/", &refname) ||
+  skip_prefix(refname, "refs/remotes/", &refname) ||
+  skip_prefix(refname, "refs/", &refname));
+
+   for (; *patterns; patterns++) {
+   if (!wildmatch(*patterns, refname, 0, NULL))
+   return 1;
+   }
+   return 0;
+}
+
+/*
+ * Return 1 if the refname matches one of the patterns, otherwise 0.
  * A pattern can be path prefix (e.g. a refname "refs/heads/master"
- * matches a pattern "refs/heads/") or a wildcard (e.g. the same ref
- * matches "refs/heads/m*",too).
+ * matches a pattern "refs/heads/" but not "refs/heads/m") or a
+ * wildcard (e.g. the same ref matches "refs/heads/m*", too).
  */
 static int match_name_as_path(const char **pattern, const char *refname)
 {
@@ -1078,6 +1102,16 @@ static int match_name_as_path(const char **pattern, 
const char *refname)
return 0;
 }
 
+/* Return 1 if the refname matches one of the patterns, otherwise 0. */
+static int filter_pattern_match(struct ref_filter *filter, const char *refname)
+{
+   if (!*filter->name_patterns)
+   return 1; /* No pattern always matches */
+   if (filter->match_as_path)
+   return match_name_as_path(filter->name_patterns, refname);
+   return match_pattern(filter->name_patterns, refname);
+}
+
 /*
  * Given a ref (sha1, refname), check if the ref belongs to the array
  * of sha1s. If the given ref is a tag, check if the given tag points
@@ -1181,7 +1215,7 @@ static int ref_filter_handler(const char *refname, const 
struct object_id *oid,
if (!(kind & filter->kind))
return 0;
 
-   if (*filter->name_patterns && 
!match_name_as_path(filter->name_patterns, refname))
+   if (!filter_pattern_match(filter, refname))
return 0;
 
if (filter->points_at.nr && !match_points_at(&filter->points_at, 
oid->hash, refname))
diff --git a/ref-filter.h b/ref-filter.h
index 5aa2f40..8241066 100644
--- a/ref-filter.h
+++ b/ref-filter.h
@@ -58,7 +58,8 @@ struct ref_filter {
} merge;
struct commit *merge_commit;
 
-   unsigned int with_commit_tag_algo : 1;
+   unsigned int with_commit_tag_algo : 1,
+   match_as_path : 1;
unsigned int kind,
lines;
 };
-- 
2.5.0

--
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 v13 07/12] ref-filter: add support to sort by version

2015-08-21 Thread Karthik Nayak
From: Karthik Nayak 

Add support to sort by version using the "v:refname" and
"version:refname" option. This is achieved by using the 'versioncmp()'
function as the comparing function for qsort.

This option is included to support sorting by versions in `git tag -l`
which will eventually be ported to use ref-filter APIs.

Add documentation and tests for the same.

Mentored-by: Christian Couder 
Mentored-by: Matthieu Moy 
Signed-off-by: Karthik Nayak 
---
 Documentation/git-for-each-ref.txt |  3 +++
 ref-filter.c   | 15 ++-
 ref-filter.h   |  3 ++-
 t/t6302-for-each-ref-filter.sh | 36 
 4 files changed, 51 insertions(+), 6 deletions(-)

diff --git a/Documentation/git-for-each-ref.txt 
b/Documentation/git-for-each-ref.txt
index 943975d..06d468e 100644
--- a/Documentation/git-for-each-ref.txt
+++ b/Documentation/git-for-each-ref.txt
@@ -154,6 +154,9 @@ For sorting purposes, fields with numeric values sort in 
numeric
 order (`objectsize`, `authordate`, `committerdate`, `taggerdate`).
 All other fields are used to sort in their byte-value order.
 
+There is also an option to sort by versions, this can be done by using
+the fieldname `version:refname` or its alias `v:refname`.
+
 In any case, a field name that refers to a field inapplicable to
 the object referred by the ref does not cause an error.  It
 returns an empty string instead.
diff --git a/ref-filter.c b/ref-filter.c
index 515147b..b4a7d72 100644
--- a/ref-filter.c
+++ b/ref-filter.c
@@ -11,6 +11,8 @@
 #include "ref-filter.h"
 #include "revision.h"
 #include "utf8.h"
+#include "git-compat-util.h"
+#include "version.h"
 
 typedef enum { FIELD_STR, FIELD_ULONG, FIELD_TIME } cmp_type;
 
@@ -1327,19 +1329,19 @@ static int cmp_ref_sorting(struct ref_sorting *s, 
struct ref_array_item *a, stru
 
get_ref_atom_value(a, s->atom, &va);
get_ref_atom_value(b, s->atom, &vb);
-   switch (cmp_type) {
-   case FIELD_STR:
+   if (s->version)
+   cmp = versioncmp(va->s, vb->s);
+   else if (cmp_type == FIELD_STR)
cmp = strcmp(va->s, vb->s);
-   break;
-   default:
+   else {
if (va->ul < vb->ul)
cmp = -1;
else if (va->ul == vb->ul)
cmp = 0;
else
cmp = 1;
-   break;
}
+
return (s->reverse) ? -cmp : cmp;
 }
 
@@ -1559,6 +1561,9 @@ int parse_opt_ref_sorting(const struct option *opt, const 
char *arg, int unset)
s->reverse = 1;
arg++;
}
+   if (skip_prefix(arg, "version:", &arg) ||
+   skip_prefix(arg, "v:", &arg))
+   s->version = 1;
len = strlen(arg);
s->atom = parse_ref_filter_atom(arg, arg+len);
return 0;
diff --git a/ref-filter.h b/ref-filter.h
index c599ea2..5aa2f40 100644
--- a/ref-filter.h
+++ b/ref-filter.h
@@ -27,7 +27,8 @@ struct atom_value;
 struct ref_sorting {
struct ref_sorting *next;
int atom; /* index into used_atom array (internal) */
-   unsigned reverse : 1;
+   unsigned reverse : 1,
+   version : 1;
 };
 
 struct ref_array_item {
diff --git a/t/t6302-for-each-ref-filter.sh b/t/t6302-for-each-ref-filter.sh
index 227992b..38c99c9 100755
--- a/t/t6302-for-each-ref-filter.sh
+++ b/t/t6302-for-each-ref-filter.sh
@@ -150,4 +150,40 @@ test_expect_success 'alignment with format quote' '
test_cmp expect actual
 '
 
+test_expect_success 'setup for version sort' '
+   test_commit foo1.3 &&
+   test_commit foo1.6 &&
+   test_commit foo1.10
+'
+
+test_expect_success 'version sort' '
+   git for-each-ref --sort=version:refname --format="%(refname:short)" 
refs/tags/ | grep "foo" >actual &&
+   cat >expect <<-\EOF &&
+   foo1.3
+   foo1.6
+   foo1.10
+   EOF
+   test_cmp expect actual
+'
+
+test_expect_success 'version sort (shortened)' '
+   git for-each-ref --sort=v:refname --format="%(refname:short)" 
refs/tags/ | grep "foo" >actual &&
+   cat >expect <<-\EOF &&
+   foo1.3
+   foo1.6
+   foo1.10
+   EOF
+   test_cmp expect actual
+'
+
+test_expect_success 'reverse version sort' '
+   git for-each-ref --sort=-version:refname --format="%(refname:short)" 
refs/tags/ | grep "foo" >actual &&
+   cat >expect <<-\EOF &&
+   foo1.10
+   foo1.6
+   foo1.3
+   EOF
+   test_cmp expect actual
+'
+
 test_done
-- 
2.5.0

--
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 v13 05/12] ref-filter: add option to filter out tags, branches and remotes

2015-08-21 Thread Karthik Nayak
From: Karthik Nayak 

Add a function called 'for_each_reftype_fullpath()' to refs.{c,h}
which iterates through each ref for the given path without trimming
the path and also accounting for broken refs, if mentioned.

Add 'filter_ref_kind()' in ref-filter.c to check the kind of ref being
handled and return the kind to 'ref_filter_handler()', where we
discard refs which we do not need and assign the kind to needed refs.

Mentored-by: Christian Couder 
Mentored-by: Matthieu Moy 
Signed-off-by: Karthik Nayak 
---
 ref-filter.c | 59 ++-
 ref-filter.h | 12 ++--
 refs.c   |  9 +
 refs.h   |  1 +
 4 files changed, 74 insertions(+), 7 deletions(-)

diff --git a/ref-filter.c b/ref-filter.c
index ffec10a..d5fae1a 100644
--- a/ref-filter.c
+++ b/ref-filter.c
@@ -1123,6 +1123,36 @@ static struct ref_array_item *new_ref_array_item(const 
char *refname,
return ref;
 }
 
+static int filter_ref_kind(struct ref_filter *filter, const char *refname)
+{
+   unsigned int i;
+
+   static struct {
+   const char *prefix;
+   unsigned int kind;
+   } ref_kind[] = {
+   { "refs/heads/" , FILTER_REFS_BRANCHES },
+   { "refs/remotes/" , FILTER_REFS_REMOTES },
+   { "refs/tags/", FILTER_REFS_TAGS}
+   };
+
+   if (filter->kind == FILTER_REFS_BRANCHES)
+   return FILTER_REFS_BRANCHES;
+   else if (filter->kind == FILTER_REFS_REMOTES)
+   return FILTER_REFS_REMOTES;
+   else if (filter->kind == FILTER_REFS_TAGS)
+   return FILTER_REFS_TAGS;
+   else if (!strcmp(refname, "HEAD"))
+   return FILTER_REFS_DETACHED_HEAD;
+
+   for (i = 0; i < ARRAY_SIZE(ref_kind); i++) {
+   if (starts_with(refname, ref_kind[i].prefix))
+   return ref_kind[i].kind;
+   }
+
+   return FILTER_REFS_OTHERS;
+}
+
 /*
  * A call-back given to for_each_ref().  Filter refs and keep them for
  * later object processing.
@@ -1133,6 +1163,7 @@ static int ref_filter_handler(const char *refname, const 
struct object_id *oid,
struct ref_filter *filter = ref_cbdata->filter;
struct ref_array_item *ref;
struct commit *commit = NULL;
+   unsigned int kind;
 
if (flag & REF_BAD_NAME) {
warning("ignoring ref with broken name %s", refname);
@@ -1144,6 +1175,10 @@ static int ref_filter_handler(const char *refname, const 
struct object_id *oid,
return 0;
}
 
+   kind = filter_ref_kind(filter, refname);
+   if (!(kind & filter->kind))
+   return 0;
+
if (*filter->name_patterns && 
!match_name_as_path(filter->name_patterns, refname))
return 0;
 
@@ -1175,6 +1210,7 @@ static int ref_filter_handler(const char *refname, const 
struct object_id *oid,
 
REALLOC_ARRAY(ref_cbdata->array->items, ref_cbdata->array->nr + 1);
ref_cbdata->array->items[ref_cbdata->array->nr++] = ref;
+   ref->kind = kind;
return 0;
 }
 
@@ -1251,16 +1287,29 @@ int filter_refs(struct ref_array *array, struct 
ref_filter *filter, unsigned int
 {
struct ref_filter_cbdata ref_cbdata;
int ret = 0;
+   unsigned int broken = 0;
 
ref_cbdata.array = array;
ref_cbdata.filter = filter;
 
/*  Simple per-ref filtering */
-   if (type & (FILTER_REFS_ALL | FILTER_REFS_INCLUDE_BROKEN))
-   ret = for_each_rawref(ref_filter_handler, &ref_cbdata);
-   else if (type & FILTER_REFS_ALL)
-   ret = for_each_ref(ref_filter_handler, &ref_cbdata);
-   else if (type)
+   if (type & FILTER_REFS_INCLUDE_BROKEN) {
+   type &= ~FILTER_REFS_INCLUDE_BROKEN;
+   broken = 1;
+   }
+
+   filter->kind = type;
+   if (type == FILTER_REFS_BRANCHES)
+   ret = for_each_reftype_fullpath(ref_filter_handler, 
"refs/heads/", broken, &ref_cbdata);
+   else if (type == FILTER_REFS_REMOTES)
+   ret = for_each_reftype_fullpath(ref_filter_handler, 
"refs/remotes/", broken, &ref_cbdata);
+   else if (type == FILTER_REFS_TAGS)
+   ret = for_each_reftype_fullpath(ref_filter_handler, 
"refs/tags/", broken, &ref_cbdata);
+   else if (type & FILTER_REFS_ALL) {
+   ret = for_each_reftype_fullpath(ref_filter_handler, "", broken, 
&ref_cbdata);
+   if (type & FILTER_REFS_DETACHED_HEAD)
+   head_ref(ref_filter_handler, &ref_cbdata);
+   } else
die("filter_refs: invalid type");
 
/*  Filters that need revision walking */
diff --git a/ref-filter.h b/ref-filter.h
index 45026d0..99f081b 100644
--- a/ref-filter.h
+++ b/ref-filter.h
@@ -13,8 +13,14 @@
 #define QUOTE_PYTHON 4
 #define QUOTE_TCL 8
 
-#define FILTER_REFS_INCLUDE_BROKEN 0x1
-#define FILTER_REFS_ALL 0x2
+#define FILTER_REFS_INCLUDE_BROKEN 0x0001
+#define FILTER_REFS_T

[PATCH v13 09/12] tag.c: use 'ref-filter' data structures

2015-08-21 Thread Karthik Nayak
From: Karthik Nayak 

Make 'tag.c' use 'ref-filter' data structures and make changes to
support the new data structures. This is a part of the process
of porting 'tag.c' to use 'ref-filter' APIs.

This is a temporary step before porting 'tag.c' to use 'ref-filter'
completely. As this is a temporary step, most of the code
introduced here will be removed when 'tag.c' is ported over to use
'ref-filter' APIs.

Mentored-by: Christian Couder 
Mentored-by: Matthieu Moy 
Signed-off-by: Karthik Nayak 
---
 builtin/tag.c | 106 +++---
 1 file changed, 57 insertions(+), 49 deletions(-)

diff --git a/builtin/tag.c b/builtin/tag.c
index 0fc7557..e96bae2 100644
--- a/builtin/tag.c
+++ b/builtin/tag.c
@@ -17,6 +17,7 @@
 #include "gpg-interface.h"
 #include "sha1-array.h"
 #include "column.h"
+#include "ref-filter.h"
 
 static const char * const git_tag_usage[] = {
N_("git tag [-a | -s | -u ] [-f] [-m  | -F ] 
 []"),
@@ -34,15 +35,6 @@ static const char * const git_tag_usage[] = {
 
 static int tag_sort;
 
-struct tag_filter {
-   const char **patterns;
-   int lines;
-   int sort;
-   struct string_list tags;
-   struct commit_list *with_commit;
-};
-
-static struct sha1_array points_at;
 static unsigned int colopts;
 
 static int match_pattern(const char **patterns, const char *ref)
@@ -61,19 +53,20 @@ static int match_pattern(const char **patterns, const char 
*ref)
  * removed as we port tag.c to use the ref-filter APIs.
  */
 static const unsigned char *match_points_at(const char *refname,
-   const unsigned char *sha1)
+   const unsigned char *sha1,
+   struct sha1_array *points_at)
 {
const unsigned char *tagged_sha1 = NULL;
struct object *obj;
 
-   if (sha1_array_lookup(&points_at, sha1) >= 0)
+   if (sha1_array_lookup(points_at, sha1) >= 0)
return sha1;
obj = parse_object(sha1);
if (!obj)
die(_("malformed object at '%s'"), refname);
if (obj->type == OBJ_TAG)
tagged_sha1 = ((struct tag *)obj)->tagged->sha1;
-   if (tagged_sha1 && sha1_array_lookup(&points_at, tagged_sha1) >= 0)
+   if (tagged_sha1 && sha1_array_lookup(points_at, tagged_sha1) >= 0)
return tagged_sha1;
return NULL;
 }
@@ -228,12 +221,24 @@ free_return:
free(buf);
 }
 
+static void ref_array_append(struct ref_array *array, const char *refname)
+{
+   size_t len = strlen(refname);
+   struct ref_array_item *ref = xcalloc(1, sizeof(struct ref_array_item) + 
len + 1);
+   memcpy(ref->refname, refname, len);
+   ref->refname[len] = '\0';
+   REALLOC_ARRAY(array->items, array->nr + 1);
+   array->items[array->nr++] = ref;
+}
+
 static int show_reference(const char *refname, const struct object_id *oid,
  int flag, void *cb_data)
 {
-   struct tag_filter *filter = cb_data;
+   struct ref_filter_cbdata *data = cb_data;
+   struct ref_array *array = data->array;
+   struct ref_filter *filter = data->filter;
 
-   if (match_pattern(filter->patterns, refname)) {
+   if (match_pattern(filter->name_patterns, refname)) {
if (filter->with_commit) {
struct commit *commit;
 
@@ -244,12 +249,12 @@ static int show_reference(const char *refname, const 
struct object_id *oid,
return 0;
}
 
-   if (points_at.nr && !match_points_at(refname, oid->hash))
+   if (filter->points_at.nr && !match_points_at(refname, 
oid->hash, &filter->points_at))
return 0;
 
if (!filter->lines) {
-   if (filter->sort)
-   string_list_append(&filter->tags, refname);
+   if (tag_sort)
+   ref_array_append(array, refname);
else
printf("%s\n", refname);
return 0;
@@ -264,36 +269,36 @@ static int show_reference(const char *refname, const 
struct object_id *oid,
 
 static int sort_by_version(const void *a_, const void *b_)
 {
-   const struct string_list_item *a = a_;
-   const struct string_list_item *b = b_;
-   return versioncmp(a->string, b->string);
+   const struct ref_array_item *a = *((struct ref_array_item **)a_);
+   const struct ref_array_item *b = *((struct ref_array_item **)b_);
+   return versioncmp(a->refname, b->refname);
 }
 
-static int list_tags(const char **patterns, int lines,
-struct commit_list *with_commit, int sort)
+static int list_tags(struct ref_filter *filter, int sort)
 {
-   struct tag_filter filter;
+   struct ref_array array;
+   struct ref_filter_cbdata data;
+
+   memset(&array, 0, si

[PATCH v13 12/12] tag.c: implement '--merged' and '--no-merged' options

2015-08-21 Thread Karthik Nayak
Use 'ref-filter' APIs to implement the '--merged' and '--no-merged'
options into 'tag.c'. The '--merged' option lets the user to only list
tags merged into the named commit. The '--no-merged' option lets the
user to only list tags not merged into the named commit.  If no object
is provided it assumes HEAD as the object.

Add documentation and tests for the same.

Mentored-by: Christian Couder 
Mentored-by: Matthieu Moy 
Signed-off-by: Karthik Nayak 
---
 Documentation/git-tag.txt |  7 ++-
 builtin/tag.c |  6 +-
 t/t7004-tag.sh| 27 +++
 3 files changed, 38 insertions(+), 2 deletions(-)

diff --git a/Documentation/git-tag.txt b/Documentation/git-tag.txt
index 0c7f4e6..3803bf7 100644
--- a/Documentation/git-tag.txt
+++ b/Documentation/git-tag.txt
@@ -14,7 +14,7 @@ SYNOPSIS
 'git tag' -d ...
 'git tag' [-n[]] -l [--contains ] [--points-at ]
[--column[=] | --no-column] [--create-reflog] [--sort=]
-   [--format=] [...]
+   [--format=] [--[no-]merged []] [...]
 'git tag' -v ...
 
 DESCRIPTION
@@ -165,6 +165,11 @@ This option is only applicable when listing tags without 
annotation lines.
that of linkgit:git-for-each-ref[1].  When unspecified,
defaults to `%(refname:short)`.
 
+--[no-]merged []::
+   Only list tags whose tips are reachable, or not reachable
+   if '--no-merged' is used, from the specified commit ('HEAD'
+   if not specified).
+
 CONFIGURATION
 -
 By default, 'git tag' in sign-with-default mode (-s) will use your
diff --git a/builtin/tag.c b/builtin/tag.c
index 4b8d6df..bbbcaed 100644
--- a/builtin/tag.c
+++ b/builtin/tag.c
@@ -23,7 +23,7 @@ static const char * const git_tag_usage[] = {
N_("git tag [-a | -s | -u ] [-f] [-m  | -F ] 
 []"),
N_("git tag -d ..."),
N_("git tag -l [-n[]] [--contains ] [--points-at ]"
-   "\n\t\t[--format=] [...]"),
+   "\n\t\t[--format=] [--[no-]merged []] 
[...]"),
N_("git tag -v ..."),
NULL
 };
@@ -355,6 +355,8 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
OPT_COLUMN(0, "column", &colopts, N_("show tag list in 
columns")),
OPT_CONTAINS(&filter.with_commit, N_("print only tags that 
contain the commit")),
OPT_WITH(&filter.with_commit, N_("print only tags that contain 
the commit")),
+   OPT_MERGED(&filter, N_("print only tags that are merged")),
+   OPT_NO_MERGED(&filter, N_("print only tags that are not 
merged")),
OPT_CALLBACK(0 , "sort", sorting_tail, N_("key"),
 N_("field name to sort on"), 
&parse_opt_ref_sorting),
{
@@ -413,6 +415,8 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
die(_("--contains option is only allowed with -l."));
if (filter.points_at.nr)
die(_("--points-at option is only allowed with -l."));
+   if (filter.merge_commit)
+   die(_("--merged and --no-merged option are only allowed with 
-l"));
if (cmdmode == 'd')
return for_each_tag_name(argv, delete_tag);
if (cmdmode == 'v')
diff --git a/t/t7004-tag.sh b/t/t7004-tag.sh
index 8987fb1..3dd2f51 100755
--- a/t/t7004-tag.sh
+++ b/t/t7004-tag.sh
@@ -1531,4 +1531,31 @@ test_expect_success '--format should list tags as per 
format given' '
test_cmp expect actual
 '
 
+test_expect_success 'setup --merged test tags' '
+   git tag mergetest-1 HEAD~2 &&
+   git tag mergetest-2 HEAD~1 &&
+   git tag mergetest-3 HEAD
+'
+
+test_expect_success '--merged cannot be used in non-list mode' '
+   test_must_fail git tag --merged=mergetest-2 foo
+'
+
+test_expect_success '--merged shows merged tags' '
+   cat >expect <<-\EOF &&
+   mergetest-1
+   mergetest-2
+   EOF
+   git tag -l --merged=mergetest-2 mergetest-* >actual &&
+   test_cmp expect actual
+'
+
+test_expect_success '--no-merged show unmerged tags' '
+   cat >expect <<-\EOF &&
+   mergetest-3
+   EOF
+   git tag -l --no-merged=mergetest-2 mergetest-* >actual &&
+   test_cmp expect actual
+'
+
 test_done
-- 
2.5.0

--
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 v13 10/12] tag.c: use 'ref-filter' APIs

2015-08-21 Thread Karthik Nayak
From: Karthik Nayak 

Make 'tag.c' use 'ref-filter' APIs for iterating through refs, sorting
and printing of refs. This removes most of the code used in 'tag.c'
replacing it with calls to the 'ref-filter' library.

Make 'tag.c' use the 'filter_refs()' function provided by 'ref-filter'
to filter out tags based on the options set.

For printing tags we use 'show_ref_array_item()' function provided by
'ref-filter'.

We improve the sorting option provided by 'tag.c' by using the sorting
options provided by 'ref-filter'. This causes the test 'invalid sort
parameter on command line' in t7004 to fail, as 'ref-filter' throws an
error for all sorting fields which are incorrect. The test is changed
to reflect the same.

Modify documentation for the same.

Mentored-by: Christian Couder 
Mentored-by: Matthieu Moy 
Signed-off-by: Karthik Nayak 
---
 Documentation/git-tag.txt |  16 ++-
 builtin/tag.c | 342 ++
 t/t7004-tag.sh|   8 +-
 3 files changed, 50 insertions(+), 316 deletions(-)

diff --git a/Documentation/git-tag.txt b/Documentation/git-tag.txt
index 84f6496..3ac4a96 100644
--- a/Documentation/git-tag.txt
+++ b/Documentation/git-tag.txt
@@ -13,7 +13,7 @@ SYNOPSIS
 [ | ]
 'git tag' -d ...
 'git tag' [-n[]] -l [--contains ] [--points-at ]
-   [--column[=] | --no-column] [--create-reflog] [...]
+   [--column[=] | --no-column] [--create-reflog] [--sort=] 
[...]
 'git tag' -v ...
 
 DESCRIPTION
@@ -94,14 +94,16 @@ OPTIONS
using fnmatch(3)).  Multiple patterns may be given; if any of
them matches, the tag is shown.
 
---sort=::
-   Sort in a specific order. Supported type is "refname"
-   (lexicographic order), "version:refname" or "v:refname" (tag
+--sort=::
+   Sort based on the key given.  Prefix `-` to sort in
+   descending order of the value. You may use the --sort= option
+   multiple times, in which case the last key becomes the primary
+   key. Also supports "version:refname" or "v:refname" (tag
names are treated as versions). The "version:refname" sort
order can also be affected by the
-   "versionsort.prereleaseSuffix" configuration variable. Prepend
-   "-" to reverse sort order. When this option is not given, the
-   sort order defaults to the value configured for the 'tag.sort'
+   "versionsort.prereleaseSuffix" configuration variable.
+   The keys supported are the same as those in `git for-each-ref`.
+   Sort order defaults to the value configured for the 'tag.sort'
variable if it exists, or lexicographic order otherwise. See
linkgit:git-config[1].
 
diff --git a/builtin/tag.c b/builtin/tag.c
index e96bae2..501fc52 100644
--- a/builtin/tag.c
+++ b/builtin/tag.c
@@ -28,278 +28,32 @@ static const char * const git_tag_usage[] = {
NULL
 };
 
-#define STRCMP_SORT 0  /* must be zero */
-#define VERCMP_SORT 1
-#define SORT_MASK   0x7fff
-#define REVERSE_SORT0x8000
-
-static int tag_sort;
-
 static unsigned int colopts;
 
-static int match_pattern(const char **patterns, const char *ref)
-{
-   /* no pattern means match everything */
-   if (!*patterns)
-   return 1;
-   for (; *patterns; patterns++)
-   if (!wildmatch(*patterns, ref, 0, NULL))
-   return 1;
-   return 0;
-}
-
-/*
- * This is currently duplicated in ref-filter.c, and will eventually be
- * removed as we port tag.c to use the ref-filter APIs.
- */
-static const unsigned char *match_points_at(const char *refname,
-   const unsigned char *sha1,
-   struct sha1_array *points_at)
-{
-   const unsigned char *tagged_sha1 = NULL;
-   struct object *obj;
-
-   if (sha1_array_lookup(points_at, sha1) >= 0)
-   return sha1;
-   obj = parse_object(sha1);
-   if (!obj)
-   die(_("malformed object at '%s'"), refname);
-   if (obj->type == OBJ_TAG)
-   tagged_sha1 = ((struct tag *)obj)->tagged->sha1;
-   if (tagged_sha1 && sha1_array_lookup(points_at, tagged_sha1) >= 0)
-   return tagged_sha1;
-   return NULL;
-}
-
-static int in_commit_list(const struct commit_list *want, struct commit *c)
-{
-   for (; want; want = want->next)
-   if (!hashcmp(want->item->object.sha1, c->object.sha1))
-   return 1;
-   return 0;
-}
-
-/*
- * The entire code segment for supporting the --contains option has been
- * copied over to ref-filter.{c,h}. This will be deleted evetually when
- * we port tag.c to use ref-filter APIs.
- */
-enum contains_result {
-   CONTAINS_UNKNOWN = -1,
-   CONTAINS_NO = 0,
-   CONTAINS_YES = 1
-};
-
-/*
- * Test whether the candidate or one of its parents is contained in the list.
- * Do not recurse to find out, though, but return -1 if inconclusive.
- */
-static enum contains_re

[PATCH v13 01/12] ref-filter: move `struct atom_value` to ref-filter.c

2015-08-21 Thread Karthik Nayak
Since atom_value is only required for the internal working of
ref-filter it doesn't belong in the public header.

Helped-by: Eric Sunshine 
Mentored-by: Christian Couder 
Mentored-by: Matthieu Moy 
Signed-off-by: Karthik Nayak 
---
 ref-filter.c | 5 +
 ref-filter.h | 5 +
 2 files changed, 6 insertions(+), 4 deletions(-)

diff --git a/ref-filter.c b/ref-filter.c
index 46963a5..e53c77e 100644
--- a/ref-filter.c
+++ b/ref-filter.c
@@ -55,6 +55,11 @@ static struct {
{ "color" },
 };
 
+struct atom_value {
+   const char *s;
+   unsigned long ul; /* used for sorting when not FIELD_STR */
+};
+
 /*
  * An atom is a valid field atom listed above, possibly prefixed with
  * a "*" to denote deref_tag().
diff --git a/ref-filter.h b/ref-filter.h
index 6bf27d8..45026d0 100644
--- a/ref-filter.h
+++ b/ref-filter.h
@@ -16,10 +16,7 @@
 #define FILTER_REFS_INCLUDE_BROKEN 0x1
 #define FILTER_REFS_ALL 0x2
 
-struct atom_value {
-   const char *s;
-   unsigned long ul; /* used for sorting when not FIELD_STR */
-};
+struct atom_value;
 
 struct ref_sorting {
struct ref_sorting *next;
-- 
2.5.0

--
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 v3] gc: save log from daemonized gc --auto and print it next time

2015-08-21 Thread Nguyễn Thái Ngọc Duy
While commit 9f673f9 (gc: config option for running --auto in
background - 2014-02-08) helps reduce some complaints about 'gc
--auto' hogging the terminal, it creates another set of problems.

The latest in this set is, as the result of daemonizing, stderr is
closed and all warnings are lost. This warning at the end of cmd_gc()
is particularly important because it tells the user how to avoid "gc
--auto" running repeatedly. Because stderr is closed, the user does
not know, naturally they complain about 'gc --auto' wasting CPU.

Daemonized gc now saves stderr to $GIT_DIR/gc.log. Following gc runs
will not be daemonized and gc.log printed out until the user removes
gc.log.

Signed-off-by: Nguyễn Thái Ngọc Duy 
---
 Let's try again. Compared to v2 [1], this version does not delete
 gc.log automatically any more. The user needs to take action, then
 delete gc.log to bring it background again.

 [1] http://thread.gmane.org/gmane.comp.version-control.git/266182/focus=266320

 builtin/gc.c | 36 +++-
 1 file changed, 35 insertions(+), 1 deletion(-)

diff --git a/builtin/gc.c b/builtin/gc.c
index bcc75d9..00a83e1 100644
--- a/builtin/gc.c
+++ b/builtin/gc.c
@@ -43,9 +43,20 @@ static struct argv_array prune_worktrees = ARGV_ARRAY_INIT;
 static struct argv_array rerere = ARGV_ARRAY_INIT;
 
 static char *pidfile;
+static struct strbuf log_filename = STRBUF_INIT;
+static int daemonized;
 
 static void remove_pidfile(void)
 {
+   if (daemonized && log_filename.len) {
+   struct stat st;
+
+   close(2);
+   if (stat(log_filename.buf, &st) ||
+   !st.st_size ||
+   rename(log_filename.buf, git_path("gc.log")))
+   unlink(log_filename.buf);
+   }
if (pidfile)
unlink(pidfile);
 }
@@ -330,13 +341,24 @@ int cmd_gc(int argc, const char **argv, const char 
*prefix)
fprintf(stderr, _("See \"git help gc\" for manual 
housekeeping.\n"));
}
if (detach_auto) {
+   struct strbuf sb = STRBUF_INIT;
+   if (strbuf_read_file(&sb, git_path("gc.log"), 0) > 0) {
+   warning(_("last gc run reported:\n"
+ "%s\n"
+ "running in foreground until %s is 
removed"),
+   sb.buf, git_path("gc.log"));
+   detach_auto = 0;
+   }
+   strbuf_release(&sb);
+   }
+   if (detach_auto) {
if (gc_before_repack())
return -1;
/*
 * failure to daemonize is ok, we'll continue
 * in foreground
 */
-   daemonize();
+   daemonized = !daemonize();
}
} else
add_repack_all_option();
@@ -349,6 +371,18 @@ int cmd_gc(int argc, const char **argv, const char *prefix)
name, (uintmax_t)pid);
}
 
+   if (daemonized) {
+   int fd;
+
+   strbuf_addstr(&log_filename, git_path("gc.log_XX"));
+   fd = xmkstemp(log_filename.buf);
+   if (fd >= 0) {
+   dup2(fd, 2);
+   close(fd);
+   } else
+   strbuf_release(&log_filename);
+   }
+
if (gc_before_repack())
return -1;
 
-- 
2.3.0.rc1.137.g477eb31

--
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 7/8] diff.h: extend "flags" field to 64 bits because we're out of bits

2015-08-21 Thread Nguyễn Thái Ngọc Duy
I renamed both "flags" and "touched_flags" fields while making this
patch to make sure I was aware of how these flags were manipulated
(besides DIFF_OPT* macros). So hopefully I didn't miss anything.

Signed-off-by: Nguyễn Thái Ngọc Duy 
---
 Resend to the right recipients. I screwed send-email up..

 builtin/commit.c | 2 +-
 diff-lib.c   | 4 ++--
 diff.c   | 2 +-
 diff.h   | 8 +---
 4 files changed, 9 insertions(+), 7 deletions(-)

diff --git a/builtin/commit.c b/builtin/commit.c
index 4cbd5ff..95f7296 100644
--- a/builtin/commit.c
+++ b/builtin/commit.c
@@ -895,7 +895,7 @@ static int prepare_to_commit(const char *index_file, const 
char *prefix,
 * submodules which were manually staged, which would
 * be really confusing.
 */
-   int diff_flags = DIFF_OPT_OVERRIDE_SUBMODULE_CONFIG;
+   diff_flags_t diff_flags = 
DIFF_OPT_OVERRIDE_SUBMODULE_CONFIG;
if (ignore_submodule_arg &&
!strcmp(ignore_submodule_arg, "all"))
diff_flags |= DIFF_OPT_IGNORE_SUBMODULES;
diff --git a/diff-lib.c b/diff-lib.c
index 241a843..ae09034 100644
--- a/diff-lib.c
+++ b/diff-lib.c
@@ -71,7 +71,7 @@ static int match_stat_with_submodule(struct diff_options 
*diffopt,
 {
int changed = ce_match_stat(ce, st, ce_option);
if (S_ISGITLINK(ce->ce_mode)) {
-   unsigned orig_flags = diffopt->flags;
+   diff_flags_t orig_flags = diffopt->flags;
if (!DIFF_OPT_TST(diffopt, OVERRIDE_SUBMODULE_CONFIG))
set_diffopt_flags_from_submodule_config(diffopt, 
ce->name);
if (DIFF_OPT_TST(diffopt, IGNORE_SUBMODULES))
@@ -516,7 +516,7 @@ int do_diff_cache(const unsigned char *tree_sha1, struct 
diff_options *opt)
return 0;
 }
 
-int index_differs_from(const char *def, int diff_flags)
+int index_differs_from(const char *def, diff_flags_t diff_flags)
 {
struct rev_info rev;
struct setup_revision_opt opt;
diff --git a/diff.c b/diff.c
index 7deac90..2485870 100644
--- a/diff.c
+++ b/diff.c
@@ -4912,7 +4912,7 @@ int diff_can_quit_early(struct diff_options *opt)
 static int is_submodule_ignored(const char *path, struct diff_options *options)
 {
int ignored = 0;
-   unsigned orig_flags = options->flags;
+   diff_flags_t orig_flags = options->flags;
if (!DIFF_OPT_TST(options, OVERRIDE_SUBMODULE_CONFIG))
set_diffopt_flags_from_submodule_config(options, path);
if (DIFF_OPT_TST(options, IGNORE_SUBMODULES))
diff --git a/diff.h b/diff.h
index f7208ad..4241aa5 100644
--- a/diff.h
+++ b/diff.h
@@ -110,13 +110,15 @@ enum diff_words_type {
DIFF_WORDS_COLOR
 };
 
+typedef uint64_t diff_flags_t;
+
 struct diff_options {
const char *orderfile;
const char *pickaxe;
const char *single_follow;
const char *a_prefix, *b_prefix;
-   unsigned flags;
-   unsigned touched_flags;
+   diff_flags_t flags;
+   diff_flags_t touched_flags;
 
/* diff-filter bits */
unsigned int filter;
@@ -347,7 +349,7 @@ extern int diff_result_code(struct diff_options *, int);
 
 extern void diff_no_index(struct rev_info *, int, const char **, const char *);
 
-extern int index_differs_from(const char *def, int diff_flags);
+extern int index_differs_from(const char *def, diff_flags_t diff_flags);
 
 extern size_t fill_textconv(struct userdiff_driver *driver,
struct diff_filespec *df,
-- 
2.3.0.rc1.137.g477eb31

--
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 8/8] Resurrect "diff-lib.c: adjust position of i-t-a entries in diff"

2015-08-21 Thread Nguyễn Thái Ngọc Duy
The original commit d95d728aba06a34394d15466045cbdabdada58a2 was
reverted in commit 78cc1a540ba127b13f2f3fd531777b57f3a9cd46 because we
were (and still are) not ready for a new world order. A lot more
investigation must be done to see what is impacted. See the 78cc1a5 for
details.

This patch takes a smaller and safer step. The new behavior is
controlled by SHIFT_INTENT_TO_ADD flag. We can gradually move more diff
users to the new behavior after we are sure it's safe to do so. This
flag is exposed to outside as "--shift-ita".

"git status" sets this flag unconditionally to display i-t-a entries
correctly. See d95d728 for details about "git status" and i-t-a entries.

Signed-off-by: Nguyễn Thái Ngọc Duy 
---
 Documentation/diff-options.txt |  6 ++
 diff-lib.c | 14 ++
 diff.c |  2 ++
 diff.h |  1 +
 t/t2203-add-intent.sh  | 20 ++--
 wt-status.c|  2 ++
 6 files changed, 43 insertions(+), 2 deletions(-)

diff --git a/Documentation/diff-options.txt b/Documentation/diff-options.txt
index d56ca90..b69db29 100644
--- a/Documentation/diff-options.txt
+++ b/Documentation/diff-options.txt
@@ -556,5 +556,11 @@ endif::git-format-patch[]
 --no-prefix::
Do not show any source or destination prefix.
 
+--shift-ita::
+   By default entries added by "git add -N" appear as an existing
+   empty file in "git diff" and a new file in "git diff --cached".
+   This option makes the entry appear as a new file in "git diff"
+   and non-existent in "git diff --cached".
+
 For more detailed explanation on these common options, see also
 linkgit:gitdiffcore[7].
diff --git a/diff-lib.c b/diff-lib.c
index ae09034..2546f5a 100644
--- a/diff-lib.c
+++ b/diff-lib.c
@@ -212,6 +212,12 @@ int run_diff_files(struct rev_info *revs, unsigned int 
option)
   ce->sha1, 
!is_null_sha1(ce->sha1),
   ce->name, 0);
continue;
+   } else if (DIFF_OPT_TST(&revs->diffopt, 
SHIFT_INTENT_TO_ADD) &&
+  ce_intent_to_add(ce)) {
+   diff_addremove(&revs->diffopt, '+', ce->ce_mode,
+  EMPTY_BLOB_SHA1_BIN, 0,
+  ce->name, 0);
+   continue;
}
 
changed = match_stat_with_submodule(&revs->diffopt, ce, 
&st,
@@ -376,6 +382,14 @@ static void do_oneway_diff(struct unpack_trees_options *o,
struct rev_info *revs = o->unpack_data;
int match_missing, cached;
 
+   /* i-t-a entries do not actually exist in the index */
+   if (DIFF_OPT_TST(&revs->diffopt, SHIFT_INTENT_TO_ADD) &&
+   idx && ce_intent_to_add(idx)) {
+   idx = NULL;
+   if (!tree)
+   return; /* nothing to diff.. */
+   }
+
/* if the entry is not checked out, don't examine work tree */
cached = o->index_only ||
(idx && ((idx->ce_flags & CE_VALID) || ce_skip_worktree(idx)));
diff --git a/diff.c b/diff.c
index 2485870..e554cad 100644
--- a/diff.c
+++ b/diff.c
@@ -3890,6 +3890,8 @@ int diff_opt_parse(struct diff_options *options, const 
char **av, int ac)
return parse_submodule_opt(options, arg);
else if (skip_prefix(arg, "--ws-error-highlight=", &arg))
return parse_ws_error_highlight(options, arg);
+   else if (!strcmp(arg, "--shift-ita"))
+   DIFF_OPT_SET(options, SHIFT_INTENT_TO_ADD);
 
/* misc options */
else if (!strcmp(arg, "-z"))
diff --git a/diff.h b/diff.h
index 4241aa5..68a4400 100644
--- a/diff.h
+++ b/diff.h
@@ -92,6 +92,7 @@ typedef struct strbuf *(*diff_prefix_fn_t)(struct 
diff_options *opt, void *data)
 #define DIFF_OPT_FUNCCONTEXT (1 << 29)
 #define DIFF_OPT_PICKAXE_IGNORE_CASE (1 << 30)
 #define DIFF_OPT_DEFAULT_FOLLOW_RENAMES (1 << 31)
+#define DIFF_OPT_SHIFT_INTENT_TO_ADD (1ULL << 32)
 
 #define DIFF_OPT_TST(opts, flag)((opts)->flags & DIFF_OPT_##flag)
 #define DIFF_OPT_TOUCHED(opts, flag)((opts)->touched_flags & 
DIFF_OPT_##flag)
diff --git a/t/t2203-add-intent.sh b/t/t2203-add-intent.sh
index d0f36a4..7c90eee 100755
--- a/t/t2203-add-intent.sh
+++ b/t/t2203-add-intent.sh
@@ -5,10 +5,24 @@ test_description='Intent to add'
 . ./test-lib.sh
 
 test_expect_success 'intent to add' '
+   test_commit 1 &&
+   git rm 1.t &&
+   echo hello >1.t &&
echo hello >file &&
echo hello >elif &&
git add -N file &&
-   git add elif
+   git add elif &&
+   git add -N 1.t
+'
+
+test_expect_success 'git status' '
+   git status --porcelain | grep -v actual >actual &&
+   cat >expect <<-\EOF &&
+   DA 1.t
+   A  elif
+A file
+   EOF
+   

[PATCH 7/8] diff.h: extend "flags" field to 64 bits because we're out of bits

2015-08-21 Thread Nguyễn Thái Ngọc Duy
I renamed both "flags" and "touched_flags" fields while making this
patch to make sure I was aware of how these flags were manipulated
(besides DIFF_OPT* macros). So hopefully I didn't miss anything.

Signed-off-by: Nguyễn Thái Ngọc Duy 
---
 builtin/commit.c | 2 +-
 diff-lib.c   | 4 ++--
 diff.c   | 2 +-
 diff.h   | 8 +---
 4 files changed, 9 insertions(+), 7 deletions(-)

diff --git a/builtin/commit.c b/builtin/commit.c
index 4cbd5ff..95f7296 100644
--- a/builtin/commit.c
+++ b/builtin/commit.c
@@ -895,7 +895,7 @@ static int prepare_to_commit(const char *index_file, const 
char *prefix,
 * submodules which were manually staged, which would
 * be really confusing.
 */
-   int diff_flags = DIFF_OPT_OVERRIDE_SUBMODULE_CONFIG;
+   diff_flags_t diff_flags = 
DIFF_OPT_OVERRIDE_SUBMODULE_CONFIG;
if (ignore_submodule_arg &&
!strcmp(ignore_submodule_arg, "all"))
diff_flags |= DIFF_OPT_IGNORE_SUBMODULES;
diff --git a/diff-lib.c b/diff-lib.c
index 241a843..ae09034 100644
--- a/diff-lib.c
+++ b/diff-lib.c
@@ -71,7 +71,7 @@ static int match_stat_with_submodule(struct diff_options 
*diffopt,
 {
int changed = ce_match_stat(ce, st, ce_option);
if (S_ISGITLINK(ce->ce_mode)) {
-   unsigned orig_flags = diffopt->flags;
+   diff_flags_t orig_flags = diffopt->flags;
if (!DIFF_OPT_TST(diffopt, OVERRIDE_SUBMODULE_CONFIG))
set_diffopt_flags_from_submodule_config(diffopt, 
ce->name);
if (DIFF_OPT_TST(diffopt, IGNORE_SUBMODULES))
@@ -516,7 +516,7 @@ int do_diff_cache(const unsigned char *tree_sha1, struct 
diff_options *opt)
return 0;
 }
 
-int index_differs_from(const char *def, int diff_flags)
+int index_differs_from(const char *def, diff_flags_t diff_flags)
 {
struct rev_info rev;
struct setup_revision_opt opt;
diff --git a/diff.c b/diff.c
index 7deac90..2485870 100644
--- a/diff.c
+++ b/diff.c
@@ -4912,7 +4912,7 @@ int diff_can_quit_early(struct diff_options *opt)
 static int is_submodule_ignored(const char *path, struct diff_options *options)
 {
int ignored = 0;
-   unsigned orig_flags = options->flags;
+   diff_flags_t orig_flags = options->flags;
if (!DIFF_OPT_TST(options, OVERRIDE_SUBMODULE_CONFIG))
set_diffopt_flags_from_submodule_config(options, path);
if (DIFF_OPT_TST(options, IGNORE_SUBMODULES))
diff --git a/diff.h b/diff.h
index f7208ad..4241aa5 100644
--- a/diff.h
+++ b/diff.h
@@ -110,13 +110,15 @@ enum diff_words_type {
DIFF_WORDS_COLOR
 };
 
+typedef uint64_t diff_flags_t;
+
 struct diff_options {
const char *orderfile;
const char *pickaxe;
const char *single_follow;
const char *a_prefix, *b_prefix;
-   unsigned flags;
-   unsigned touched_flags;
+   diff_flags_t flags;
+   diff_flags_t touched_flags;
 
/* diff-filter bits */
unsigned int filter;
@@ -347,7 +349,7 @@ extern int diff_result_code(struct diff_options *, int);
 
 extern void diff_no_index(struct rev_info *, int, const char **, const char *);
 
-extern int index_differs_from(const char *def, int diff_flags);
+extern int index_differs_from(const char *def, diff_flags_t diff_flags);
 
 extern size_t fill_textconv(struct userdiff_driver *driver,
struct diff_filespec *df,
-- 
2.3.0.rc1.137.g477eb31

--
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/8] grep: make it clear i-t-a entries are ignored

2015-08-21 Thread Nguyễn Thái Ngọc Duy
The expression "!S_ISREG(ce)" covers i-t-a entries as well because
ce->ce_mode would be zero then. I could make a comment saying that, but
it's probably better just to comment with code, in case i-t-a entry
content changes in future.

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

diff --git a/builtin/grep.c b/builtin/grep.c
index d04f440..f508179 100644
--- a/builtin/grep.c
+++ b/builtin/grep.c
@@ -375,7 +375,7 @@ static int grep_cache(struct grep_opt *opt, const struct 
pathspec *pathspec, int
 
for (nr = 0; nr < active_nr; nr++) {
const struct cache_entry *ce = active_cache[nr];
-   if (!S_ISREG(ce->ce_mode))
+   if (!S_ISREG(ce->ce_mode) || ce_intent_to_add(ce))
continue;
if (!ce_path_match(ce, pathspec, NULL))
continue;
-- 
2.3.0.rc1.137.g477eb31

--
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/8] checkout(-index): do not checkout i-t-a entries

2015-08-21 Thread Nguyễn Thái Ngọc Duy
The cached blob of i-t-a entries are empty blob. By checkout, we delete
the content we have. Don't do it.

This is done higher up instead of inside checkout_entry() because we
would have limited options in there: silently ignore, loudly ignore,
die. At higher level we can do better reporting. For example, "git
checkout -- foo" will complain that "foo" does not match pathspec, just
like when "foo" is not registered with "git add -N"

Signed-off-by: Nguyễn Thái Ngọc Duy 
---
 builtin/checkout-index.c |  5 -
 builtin/checkout.c   |  2 ++
 t/t2203-add-intent.sh| 34 ++
 3 files changed, 40 insertions(+), 1 deletion(-)

diff --git a/builtin/checkout-index.c b/builtin/checkout-index.c
index 8028c37..eca975d 100644
--- a/builtin/checkout-index.c
+++ b/builtin/checkout-index.c
@@ -56,7 +56,8 @@ static int checkout_file(const char *name, const char *prefix)
while (pos < active_nr) {
struct cache_entry *ce = active_cache[pos];
if (ce_namelen(ce) != namelen ||
-   memcmp(ce->name, name, namelen))
+   memcmp(ce->name, name, namelen) ||
+   ce_intent_to_add(ce))
break;
has_same_name = 1;
pos++;
@@ -99,6 +100,8 @@ static void checkout_all(const char *prefix, int 
prefix_length)
if (ce_stage(ce) != checkout_stage
&& (CHECKOUT_ALL != checkout_stage || !ce_stage(ce)))
continue;
+   if (ce_intent_to_add(ce))
+   continue;
if (prefix && *prefix &&
(ce_namelen(ce) <= prefix_length ||
 memcmp(prefix, ce->name, prefix_length)))
diff --git a/builtin/checkout.c b/builtin/checkout.c
index e1403be..02889d4 100644
--- a/builtin/checkout.c
+++ b/builtin/checkout.c
@@ -300,6 +300,8 @@ static int checkout_paths(const struct checkout_opts *opts,
 * anything to this entry at all.
 */
continue;
+   if (ce_intent_to_add(ce))
+   continue;
/*
 * Either this entry came from the tree-ish we are
 * checking the paths out of, or we are checking out
diff --git a/t/t2203-add-intent.sh b/t/t2203-add-intent.sh
index 96c8755..d0f36a4 100755
--- a/t/t2203-add-intent.sh
+++ b/t/t2203-add-intent.sh
@@ -111,5 +111,39 @@ test_expect_success 'apply:check_preimage() not creating 
empty file' '
)
 '
 
+test_expect_success 'checkout ignores i-t-a' '
+   git init checkout &&
+   (
+   cd checkout &&
+   echo data >file &&
+   git add -N file &&
+   test_must_fail git checkout -- file &&
+   echo data >expected &&
+   test_cmp expected file
+   )
+'
+
+test_expect_success 'checkout-index ignores i-t-a' '
+   (
+   cd checkout &&
+   git checkout-index file &&
+   echo data >expected &&
+   test_cmp expected file
+   )
+'
+
+test_expect_success 'checkout-index --all ignores i-t-a' '
+   (
+   cd checkout &&
+   echo data >anotherfile &&
+   git add anotherfile &&
+   rm anotherfile &&
+   git checkout-index --all &&
+   echo data >expected &&
+   test_cmp expected file &&
+   test_cmp expected anotherfile
+   )
+'
+
 test_done
 
-- 
2.3.0.rc1.137.g477eb31

--
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/8] apply: fix adding new files on i-t-a entries

2015-08-21 Thread Nguyễn Thái Ngọc Duy
Applying a patch that adds a file when that file is registered with "git
add -N" will fail with message "already exists in index" because
git-apply checks, sees those i-t-a entries and aborts. git-apply does
not realize those are for bookkeeping only, they do not really exist in
the index. This patch tightens the "exists in index" check, ignoring
i-t-a entries.

Reported-by: Patrick Higgins 
Reported-by: Bjørnar Snoksrud 
Signed-off-by: Nguyễn Thái Ngọc Duy 
---
 builtin/apply.c   |  9 +
 t/t2203-add-intent.sh | 13 +
 2 files changed, 18 insertions(+), 4 deletions(-)

diff --git a/builtin/apply.c b/builtin/apply.c
index 54aba4e..76b58a1 100644
--- a/builtin/apply.c
+++ b/builtin/apply.c
@@ -3553,10 +3553,11 @@ static int check_to_create(const char *new_name, int 
ok_if_exists)
 {
struct stat nst;
 
-   if (check_index &&
-   cache_name_pos(new_name, strlen(new_name)) >= 0 &&
-   !ok_if_exists)
-   return EXISTS_IN_INDEX;
+   if (check_index && !ok_if_exists) {
+   int pos = cache_name_pos(new_name, strlen(new_name));
+   if (pos >= 0 && !ce_intent_to_add(active_cache[pos]))
+   return EXISTS_IN_INDEX;
+   }
if (cached)
return 0;
 
diff --git a/t/t2203-add-intent.sh b/t/t2203-add-intent.sh
index 2a4a749..bb5ef2b 100755
--- a/t/t2203-add-intent.sh
+++ b/t/t2203-add-intent.sh
@@ -82,5 +82,18 @@ test_expect_success 'cache-tree invalidates i-t-a paths' '
test_cmp expect actual
 '
 
+test_expect_success 'apply adds new file on i-t-a entry' '
+   git init apply &&
+   (
+   cd apply &&
+   echo newcontent >newfile &&
+   git add newfile &&
+   git diff --cached >patch &&
+   rm .git/index &&
+   git add -N newfile &&
+   git apply --cached patch
+   )
+'
+
 test_done
 
-- 
2.3.0.rc1.137.g477eb31

--
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/8] apply: make sure check_preimage() does not leave empty file on error

2015-08-21 Thread Nguyễn Thái Ngọc Duy
The test case probably describes the test scenario the best. We have a
patch to modify some file but the base file is gone. Because
check_preimage() finds an index entry with the same old_name, it tries
to restore the on-disk base file with cached content with
checkout_target() and move on.

If this old_name is i-t-a, before this patch "apply -3" will call
checkout_target() which will write an empty file (i-t-a entries always
have "empty blob" SHA-1), then it'll fail at verify_index_match()
(i-t-a entries are always "modified") and the operation is aborted.

This empty file should not be created. Compare to the case where
old_name does not exist in index, "apply -3" fails with a different
error message "...: does not exist" but it does not touch
worktree. This patch makes sure the same happens to i-t-a entries.

load_current() shares the same code pattern (look up an index entry,
if on-disk version is not found, restore using the cached
version). Fix it too (even though it's not exercised in any test case)

Signed-off-by: Nguyễn Thái Ngọc Duy 
---
 builtin/apply.c   |  4 ++--
 t/t2203-add-intent.sh | 16 
 2 files changed, 18 insertions(+), 2 deletions(-)

diff --git a/builtin/apply.c b/builtin/apply.c
index 76b58a1..b185c97 100644
--- a/builtin/apply.c
+++ b/builtin/apply.c
@@ -3348,7 +3348,7 @@ static int load_current(struct image *image, struct patch 
*patch)
die("BUG: patch to %s is not a creation", patch->old_name);
 
pos = cache_name_pos(name, strlen(name));
-   if (pos < 0)
+   if (pos < 0 || ce_intent_to_add(active_cache[pos]))
return error(_("%s: does not exist in index"), name);
ce = active_cache[pos];
if (lstat(name, &st)) {
@@ -3501,7 +3501,7 @@ static int check_preimage(struct patch *patch, struct 
cache_entry **ce, struct s
 
if (check_index && !previous) {
int pos = cache_name_pos(old_name, strlen(old_name));
-   if (pos < 0) {
+   if (pos < 0 || ce_intent_to_add(active_cache[pos])) {
if (patch->is_new < 0)
goto is_new;
return error(_("%s: does not exist in index"), 
old_name);
diff --git a/t/t2203-add-intent.sh b/t/t2203-add-intent.sh
index bb5ef2b..96c8755 100755
--- a/t/t2203-add-intent.sh
+++ b/t/t2203-add-intent.sh
@@ -95,5 +95,21 @@ test_expect_success 'apply adds new file on i-t-a entry' '
)
 '
 
+test_expect_success 'apply:check_preimage() not creating empty file' '
+   git init check-preimage &&
+   (
+   cd check-preimage &&
+   echo oldcontent >newfile &&
+   git add newfile &&
+   echo newcontent >newfile &&
+   git diff >patch &&
+   rm .git/index &&
+   git add -N newfile &&
+   rm newfile &&
+   test_must_fail git apply -3 patch &&
+   ! test -f newfile
+   )
+'
+
 test_done
 
-- 
2.3.0.rc1.137.g477eb31

--
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/8] blame: remove obsolete comment

2015-08-21 Thread Nguyễn Thái Ngọc Duy
That "someday" in the comment happened two years later in
b65982b (Optimize "diff-index --cached" using cache-tree - 2009-05-20)

Signed-off-by: Nguyễn Thái Ngọc Duy 
---
 builtin/blame.c | 5 -
 1 file changed, 5 deletions(-)

diff --git a/builtin/blame.c b/builtin/blame.c
index 4db01c1..942f302 100644
--- a/builtin/blame.c
+++ b/builtin/blame.c
@@ -2379,11 +2379,6 @@ static struct commit *fake_working_tree_commit(struct 
diff_options *opt,
ce->ce_mode = create_ce_mode(mode);
add_cache_entry(ce, ADD_CACHE_OK_TO_ADD|ADD_CACHE_OK_TO_REPLACE);
 
-   /*
-* We are not going to write this out, so this does not matter
-* right now, but someday we might optimize diff-index --cached
-* with cache-tree information.
-*/
cache_tree_invalidate_path(&the_index, path);
 
return commit;
-- 
2.3.0.rc1.137.g477eb31

--
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/8] Add and use convenient macro ce_intent_to_add()

2015-08-21 Thread Nguyễn Thái Ngọc Duy
Signed-off-by: Nguyễn Thái Ngọc Duy 
---
 builtin/rm.c | 2 +-
 cache-tree.c | 2 +-
 cache.h  | 1 +
 read-cache.c | 4 ++--
 4 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/builtin/rm.c b/builtin/rm.c
index 80b972f..8829b09 100644
--- a/builtin/rm.c
+++ b/builtin/rm.c
@@ -211,7 +211,7 @@ static int check_local_mod(unsigned char *head, int 
index_only)
 * "intent to add" entry.
 */
if (local_changes && staged_changes) {
-   if (!index_only || !(ce->ce_flags & CE_INTENT_TO_ADD))
+   if (!index_only || !ce_intent_to_add(ce))
string_list_append(&files_staged, name);
}
else if (!index_only) {
diff --git a/cache-tree.c b/cache-tree.c
index feace8b..c865bd2 100644
--- a/cache-tree.c
+++ b/cache-tree.c
@@ -377,7 +377,7 @@ static int update_one(struct cache_tree *it,
 * they are not part of generated trees. Invalidate up
 * to root to force cache-tree users to read elsewhere.
 */
-   if (ce->ce_flags & CE_INTENT_TO_ADD) {
+   if (ce_intent_to_add(ce)) {
to_invalidate = 1;
continue;
}
diff --git a/cache.h b/cache.h
index 4e25271..41d811c 100644
--- a/cache.h
+++ b/cache.h
@@ -241,6 +241,7 @@ static inline unsigned create_ce_flags(unsigned stage)
 #define ce_uptodate(ce) ((ce)->ce_flags & CE_UPTODATE)
 #define ce_skip_worktree(ce) ((ce)->ce_flags & CE_SKIP_WORKTREE)
 #define ce_mark_uptodate(ce) ((ce)->ce_flags |= CE_UPTODATE)
+#define ce_intent_to_add(ce) ((ce)->ce_flags & CE_INTENT_TO_ADD)
 
 #define ce_permissions(mode) (((mode) & 0100) ? 0755 : 0644)
 static inline unsigned int create_ce_mode(unsigned int mode)
diff --git a/read-cache.c b/read-cache.c
index 89dbc08..f849cbd 100644
--- a/read-cache.c
+++ b/read-cache.c
@@ -327,7 +327,7 @@ int ie_match_stat(const struct index_state *istate,
 * by definition never matches what is in the work tree until it
 * actually gets added.
 */
-   if (ce->ce_flags & CE_INTENT_TO_ADD)
+   if (ce_intent_to_add(ce))
return DATA_CHANGED | TYPE_CHANGED | MODE_CHANGED;
 
changed = ce_match_stat_basic(ce, st);
@@ -1251,7 +1251,7 @@ int refresh_index(struct index_state *istate, unsigned 
int flags,
 
if (cache_errno == ENOENT)
fmt = deleted_fmt;
-   else if (ce->ce_flags & CE_INTENT_TO_ADD)
+   else if (ce_intent_to_add(ce))
fmt = added_fmt; /* must be before other checks 
*/
else if (changed & TYPE_CHANGED)
fmt = typechange_fmt;
-- 
2.3.0.rc1.137.g477eb31

--
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 0/8] Resurrect "diff-lib.c: adjust position of i-t-a entries in diff"

2015-08-21 Thread Nguyễn Thái Ngọc Duy
On Thu, Jun 25, 2015 at 8:07 PM, Junio C Hamano  wrote:
>>> Perhaps a good and safe way forward to resurrect what d95d728a
>>> wanted to do is to first add an option to tell run_diff_index() and
>>> run_diff_files() which behaviour the caller wants to see, add that
>>> only to the caller in wt-status.c?  Then incrementally pass that
>>> option from more callsites that we are absolutely certain that want
>>> this different worldview with respect to i-t-a?
>>
>> Agreed.
>
> OK.  Perhaps then first I should do that revert and we'll
> incrementally rebuild on top.

Here comes the rebuild. This adds --shift-ita option (and an internal
flag) to enable this behavior. Those only take the last two patches.
The remaining is to make sure we handle i-t-a entries correctly in
some commands.

Nguyễn Thái Ngọc Duy (8):
  blame: remove obsolete comment
  Add and use convenient macro ce_intent_to_add()
  apply: fix adding new files on i-t-a entries
  apply: make sure check_preimage() does not leave empty file on error
  checkout(-index): do not checkout i-t-a entries
  grep: make it clear i-t-a entries are ignored
  diff.h: extend "flags" field to 64 bits because we're out of bits
  Resurrect "diff-lib.c: adjust position of i-t-a entries in diff"

 Documentation/diff-options.txt |  6 +++
 builtin/apply.c| 13 ---
 builtin/blame.c|  5 ---
 builtin/checkout-index.c   |  5 ++-
 builtin/checkout.c |  2 +
 builtin/commit.c   |  2 +-
 builtin/grep.c |  2 +-
 builtin/rm.c   |  2 +-
 cache-tree.c   |  2 +-
 cache.h|  1 +
 diff-lib.c | 18 -
 diff.c |  4 +-
 diff.h |  9 +++--
 read-cache.c   |  4 +-
 t/t2203-add-intent.sh  | 83 +-
 wt-status.c|  2 +
 16 files changed, 134 insertions(+), 26 deletions(-)

-- 
2.3.0.rc1.137.g477eb31

--
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/5] clone: better error when --reference is a linked checkout

2015-08-21 Thread Nguyễn Thái Ngọc Duy
Signed-off-by: Nguyễn Thái Ngọc Duy 
---
 builtin/clone.c | 7 ++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/builtin/clone.c b/builtin/clone.c
index 836fb64..7a010bb 100644
--- a/builtin/clone.c
+++ b/builtin/clone.c
@@ -294,9 +294,14 @@ static int add_one_reference(struct string_list_item 
*item, void *cb_data)
char *ref_git_git = mkpathdup("%s/.git", ref_git);
free(ref_git);
ref_git = ref_git_git;
-   } else if (!is_directory(mkpath("%s/objects", ref_git)))
+   } else if (!is_directory(mkpath("%s/objects", ref_git))) {
+   struct strbuf sb = STRBUF_INIT;
+   if (get_common_dir(&sb, ref_git))
+   die(_("reference repository '%s' as a linked checkout 
is not supported yet."),
+   item->string);
die(_("reference repository '%s' is not a local repository."),
item->string);
+   }
 
if (!access(mkpath("%s/shallow", ref_git), F_OK))
die(_("reference repository '%s' is shallow"), item->string);
-- 
2.3.0.rc1.137.g477eb31

--
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 0/5] fix local clone from a linked checkout

2015-08-21 Thread Nguyễn Thái Ngọc Duy
On Wed, Jul 15, 2015 at 8:25 PM, Duy Nguyen  wrote:
> On Wed, Jul 15, 2015 at 11:40:18AM +0200, Bjørnar Snoksrud wrote:
>> I reported this before, but now I have a nice topic to hang it on -
>>
>> I have re-reproduced the bug using a build from master as of today,
>> using the new worktree commands.
>
> Something like the following patch should work if you need it now.
>
> Because this may conflict (in the test cases) with Eric's series to
> move "git checkout --to" to "git worktree add", and because the next
> release is already delayed to let "git worktree add" in, I think we
> could keep this patch out of tree for now. I will split it up, add
> tests and resubmit once the release is out. Please remind me if you
> see nothing from me for too long.

Here it is. Mostly the same as the previous patch except that the last
patch is new.

Nguyễn Thái Ngọc Duy (5):
  path.c: delete an extra space
  enter_repo: avoid duplicating logic, use is_git_directory() instead
  enter_repo: allow .git files in strict mode
  clone: allow --local from a linked checkout
  clone: better error when --reference is a linked checkout

 builtin/clone.c | 13 ++---
 path.c  | 14 +-
 t/t2025-worktree-add.sh |  5 +
 3 files changed, 24 insertions(+), 8 deletions(-)

-- 
2.3.0.rc1.137.g477eb31

--
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/5] enter_repo: avoid duplicating logic, use is_git_directory() instead

2015-08-21 Thread Nguyễn Thái Ngọc Duy
Signed-off-by: Nguyễn Thái Ngọc Duy 
---
 path.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/path.c b/path.c
index a536ee3..7340e11 100644
--- a/path.c
+++ b/path.c
@@ -441,8 +441,7 @@ const char *enter_repo(const char *path, int strict)
else if (chdir(path))
return NULL;
 
-   if (access("objects", X_OK) == 0 && access("refs", X_OK) == 0 &&
-   validate_headref("HEAD") == 0) {
+   if (is_git_directory(".")) {
set_git_dir(".");
check_repository_format();
return path;
-- 
2.3.0.rc1.137.g477eb31

--
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/5] enter_repo: allow .git files in strict mode

2015-08-21 Thread Nguyễn Thái Ngọc Duy
Strict mode is about not guessing where .git is. If the user points to a
.git file, we know exactly where the target .git dir will be.

Signed-off-by: Nguyễn Thái Ngọc Duy 
---
 path.c | 9 +++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/path.c b/path.c
index 7340e11..32d4ca6 100644
--- a/path.c
+++ b/path.c
@@ -438,8 +438,13 @@ const char *enter_repo(const char *path, int strict)
return NULL;
path = validated_path;
}
-   else if (chdir(path))
-   return NULL;
+   else {
+   const char *gitfile = read_gitfile(used_path);
+   if (gitfile)
+   path = gitfile;
+   if (chdir(path))
+   return NULL;
+   }
 
if (is_git_directory(".")) {
set_git_dir(".");
-- 
2.3.0.rc1.137.g477eb31

--
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/5] clone: allow --local from a linked checkout

2015-08-21 Thread Nguyễn Thái Ngọc Duy
Noticed-by: Bjørnar Snoksrud 
Signed-off-by: Nguyễn Thái Ngọc Duy 
---
 builtin/clone.c | 6 --
 t/t2025-worktree-add.sh | 5 +
 2 files changed, 9 insertions(+), 2 deletions(-)

diff --git a/builtin/clone.c b/builtin/clone.c
index 578da85..836fb64 100644
--- a/builtin/clone.c
+++ b/builtin/clone.c
@@ -424,8 +424,10 @@ static void clone_local(const char *src_repo, const char 
*dest_repo)
} else {
struct strbuf src = STRBUF_INIT;
struct strbuf dest = STRBUF_INIT;
-   strbuf_addf(&src, "%s/objects", src_repo);
-   strbuf_addf(&dest, "%s/objects", dest_repo);
+   get_common_dir(&src, src_repo);
+   get_common_dir(&dest, dest_repo);
+   strbuf_addstr(&src, "/objects");
+   strbuf_addf(&dest, "/objects");
copy_or_link_directory(&src, &dest, src_repo, src.len);
strbuf_release(&src);
strbuf_release(&dest);
diff --git a/t/t2025-worktree-add.sh b/t/t2025-worktree-add.sh
index 8267411..3694174 100755
--- a/t/t2025-worktree-add.sh
+++ b/t/t2025-worktree-add.sh
@@ -193,4 +193,9 @@ test_expect_success '"add" -B/--detach mutually exclusive' '
test_must_fail git worktree add -B poodle --detach bamboo master
 '
 
+test_expect_success 'local clone from linked checkout' '
+   git clone --local here here-clone &&
+   ( cd here-clone && git fsck )
+'
+
 test_done
-- 
2.3.0.rc1.137.g477eb31

--
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/5] path.c: delete an extra space

2015-08-21 Thread Nguyễn Thái Ngọc Duy
Signed-off-by: Nguyễn Thái Ngọc Duy 
---
 path.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/path.c b/path.c
index 95acbaf..a536ee3 100644
--- a/path.c
+++ b/path.c
@@ -431,7 +431,7 @@ const char *enter_repo(const char *path, int strict)
}
if (!suffix[i])
return NULL;
-   gitfile = read_gitfile(used_path) ;
+   gitfile = read_gitfile(used_path);
if (gitfile)
strcpy(used_path, gitfile);
if (chdir(used_path))
-- 
2.3.0.rc1.137.g477eb31

--
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: Where to report security vulnerabilities in git?

2015-08-21 Thread Junio C Hamano
On Fri, Aug 21, 2015 at 3:55 PM, Guido Vranken  wrote:
> germane exploitation details. I did find an older thread in the
> archive addressing this question (
> http://thread.gmane.org/gmane.comp.version-control.git/260328/ ), but
> because I'm unsure if those e-mail addresses are still relevant, I'm
> asking again.

Indeed that was an old advice. Recent releases of "A note from the
maintainer" has this paragraph:

If you think you found a security-sensitive issue and want to disclose
it to us without announcing it to wider public, please contact us at
our security mailing list .
--
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: Submodule, subtree, or something else?

2015-08-21 Thread Stefan Beller
On Fri, Aug 21, 2015 at 3:47 PM, Jānis Rukšāns  wrote:
> Hello,
>
>
> First of all, I apologise for the wall of text that follows; obviously I
> am bad at this.
>
> My $DAYJOB is switching from Subversion to Git, primarily because of
> it's distributed nature (we are scattered all across the globe), and the
> ease of branching and merging.  One issue that has popped up is how to
> manage code shared between multiple projects.
>
> Our SVN setup used a shared repository for all projects, either using
> externals for shared code, or, more often than not, simply merging the
> code between projects as needed.  Ignoring the fact that merging with
> SVN is somewhat cumbersome, overall it has worked quite well for us,
> especially when combined with git-svn.
>
> For external libraries that rarely change, submodules appear to be the
> obvious choice when using Git.  On the other hand, I've found them
> somewhat cumbersome to use, and subtree merging (either using git
> subtree, or directly with git merge -s subtree) is closer to what we
> were doing in SVN.  A major drawback of submodules in my opinion is the
> inability to make a full clone from an existing one without having
> access to the central repository, which is something I have to do from
> time to time.

Can you elaborate on that a bit more?
git clone --recurse-submodules should do that no matter which remote
you contact?


>
> For internal libraries, the situation is even less clear.  For many of
> these libraries, most of the development happens within the context of a
> single project, with commits to main project being interleaved with
> commits to the subproject(s), resulting in histories resembling:
>
>  (using git submodule)
>
>A---B---S1---S2---C---S3
>   ,´   ,´   ,´
>  N---OPQ---R
>
>  (using git subtree with --rejoin)
>
>A---B---N---O---M1---M2---Q---C---R---M3
>   ///
>  N'--O'---PQ'--R'
>
>  (using merge -s subtree)
>
>A---B---M1---M2---C---M3
>   ///
>  N---OPQ---R
>
> where A, B and C are changes to the main project, N, O, P, Q and R are
> changes to library code, and Sn and Mn are submodule updates and merge
> commits, respectively.
>
> From what I have gathered, submodules have issues with branching and
> merging, therefore, unless I'm mistaken, submodules are kinda out of
> question.  Of the remaining two options, merging directly results in a
> nicer history, but requires making all changes to the library repo first
> (although I am quite sure that a similar effect can be achieved with
> plumbing, similarly to how git subtree split works), and is harder to
> use than git subtree.  Also, all three options can result in the main
> project history being cluttered with extra commits.
>
> Lastly, there is a particularly painful 3rd party library that has an
> enormous amount of local modifications that are never going to make it
> upstream, essentially making it a fork, project specific changes that
> are required for one project, but would break others, separate language
> bindings that access the internals (often requiring bug fixes to be made
> simultaneously to both), and, if that wasn't enough, it *requires*
> several source files to be modified for each individual project that
> uses it.  It's a complete mess, but we're stuck with it for the existing
> projects, as switching to an alternative would be too time consuming.
>
>
> To sum up, I'm looking for something that would let us share code
> between multiple projects, allow for:
>
> 1) separate histories with relatively easy branching and merging
>
> 2) distributed workflow without having to set up a multiple repositories
> everywhere (eg. work <-> home <-> laptop)
>
> 3) to work on the shared code within a project using it
>
> 4) inspection of the complete history
>
> 5) modifications that are not shared with other projects
>
> and would not result in lots of clutter in the history.
>
> Repository size is somewhat less of an issue, because each submodule has
> to be checked out anyway.
>
> Submodules let you have #3, and #1, #2 and #5 to a point, after which it
> becomes a pain.  git subtree allows #1, #2, #3 and #4, and #5 with some
> pain (?), but results in duplicate commits.  Using subtree merge
> strategy directly gives everything except #3, but is harder to use than
> submodules or subtree.
>
> Are there any other options beside these three for sharing (or in some
> cases, not sharing) common code between projects using Git, that would
> address the above points better?  Or, alternatively, ways to work around
> the drawbacks of the existing tools?
>
> Lastly, I will be grateful for any suggestions about how to handle the
> messy case described above better.
>
> Thanks,
> Jānis
>
> --
> 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

Re: Where to report security vulnerabilities in git?

2015-08-21 Thread Stefan Beller
The addresses are still valid. (I think there was a plan to introduce
a git-security@...
but I am not sure if that happened.)

> Current practice is to contact Junio C Hamano  pobox.com>.
> Cc-ing Jeff King  peff.net> isn't a bad idea while at it.

Just go for that.


On Fri, Aug 21, 2015 at 3:55 PM, Guido Vranken  wrote:
> List,
>
> I would like to report security vulnerabilities in git. Due to the
> sensitive nature of security-impacting bugs I would like to know if
> there's a dedicated e-mail address for this, so that the issues at
> play can be patched prior to a coordinated public disclosure of the
> germane exploitation details. I did find an older thread in the
> archive addressing this question (
> http://thread.gmane.org/gmane.comp.version-control.git/260328/ ), but
> because I'm unsure if those e-mail addresses are still relevant, I'm
> asking again.
>
> Thanks.
>
> Guido
> --
> 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: [RFC PATCH 2/3] run-commands: add an async queue processor

2015-08-21 Thread Stefan Beller
On Fri, Aug 21, 2015 at 12:44 PM, Jeff King  wrote:
> On Fri, Aug 21, 2015 at 12:05:13PM -0700, Junio C Hamano wrote:
>
>> The primary reason I suspect is because you sent to a wrong set of
>> people.  Submodule folks have largely been working in the scripted
>> ones, and may not necessarily be the ones who are most familiar with
>> the run-command infrastructure.
>>
>> "shortlog --no-merges" tells me that the obvious suspects are j6t
>> and peff.
>
> No good deed goes unpunished. ;)
>
> Before even looking at the implementation, my first question would be
> whether this pattern is applicable in several places in git (i.e., is it
> worth the extra complexity of abstracting out in the first place). I
> think there are a few task-queue patterns already in git; for example
> the delta search in pack-objects. Is the interface given here sufficient
> to convert pack-objects? Is the result nicer to read? Is it as
> efficient?

I have converted index-pack threading now, and it looks quite easy:

diff --git a/builtin/index-pack.c b/builtin/index-pack.c
index 3f10840..159ee36 100644
--- a/builtin/index-pack.c
+++ b/builtin/index-pack.c
@@ -11,6 +11,7 @@
 #include "exec_cmd.h"
 #include "streaming.h"
 #include "thread-utils.h"
+#include "run-command.h"

 static const char index_pack_usage[] =
 "git index-pack [-v] [-o ] [--keep | --keep=]
[--verify] [--strict] ( | --stdin [--fix-thin]
[])";
@@ -1075,7 +1076,7 @@ static void resolve_base(struct object_entry *obj)
 }

 #ifndef NO_PTHREADS
-static void *threaded_second_pass(void *data)
+static int threaded_second_pass(struct task_queue *tq, void *data)
 {
set_thread_data(data);
for (;;) {
@@ -1096,7 +1097,7 @@ static void *threaded_second_pass(void *data)

resolve_base(&objects[i]);
}
-   return NULL;
+   return 0;
 }
 #endif

@@ -1195,18 +1196,18 @@ static void resolve_deltas(void)
  nr_ref_deltas + nr_ofs_deltas);

 #ifndef NO_PTHREADS
-   nr_dispatched = 0;
if (nr_threads > 1 || getenv("GIT_FORCE_THREADS")) {
+   nr_dispatched = 0;
init_thread();
-   for (i = 0; i < nr_threads; i++) {
-   int ret = pthread_create(&thread_data[i].thread, NULL,
-threaded_second_pass,
thread_data + i);
-   if (ret)
-   die(_("unable to create thread: %s"),
-   strerror(ret));
-   }
+
+   tq = create_task_queue(nr_threads);
+
for (i = 0; i < nr_threads; i++)
-   pthread_join(thread_data[i].thread, NULL);
+   add_task(tq, threaded_second_pass, thread_data + i);
+
+   if (finish_task_queue(tq))
+   die("Not all threads have finished");
+
cleanup_thread();
return;
}
---
(tests pass)
This was cheating as I picked to convert index-pack as opposed to upload-pack
(index-pack is very similar to a queued workload. This was just moving
the thread
creation into the new proposed queue processor.)

I realize now this can be adapted a bit more, to show off the queue features
but would require a larger rewrite. So instead of just creating the threads and
then locking, we get rid of the worker lock like this:

diff --git a/builtin/index-pack.c b/builtin/index-pack.c
index 3f10840..797efea 100644
--- a/builtin/index-pack.c
+++ b/builtin/index-pack.c
@@ -11,6 +11,7 @@
 #include "exec_cmd.h"
 #include "streaming.h"
 #include "thread-utils.h"
+#include "run-command.h"

 static const char index_pack_usage[] =
 "git index-pack [-v] [-o ] [--keep | --keep=]
[--verify] [--strict] ( | --stdin [--fix-thin]
[])";
@@ -106,10 +107,6 @@ static pthread_mutex_t counter_mutex;
 #define counter_lock() lock_mutex(&counter_mutex)
 #define counter_unlock() unlock_mutex(&counter_mutex)

-static pthread_mutex_t work_mutex;
-#define work_lock() lock_mutex(&work_mutex)
-#define work_unlock() unlock_mutex(&work_mutex)
-
 static pthread_mutex_t deepest_delta_mutex;
 #define deepest_delta_lock() lock_mutex(&deepest_delta_mutex)
 #define deepest_delta_unlock() unlock_mutex(&deepest_delta_mutex)
@@ -140,7 +137,6 @@ static void init_thread(void)
  int i;
  init_recursive_mutex(&read_mutex);
  pthread_mutex_init(&counter_mutex, NULL);
- pthread_mutex_init(&work_mutex, NULL);
  pthread_mutex_init(&type_cas_mutex, NULL);
  if (show_stat)
  pthread_mutex_init(&deepest_delta_mutex, NULL);
@@ -163,7 +159,6 @@ static void cleanup_thread(void)
  threads_active = 0;
  pthread_mutex_destroy(&read_mutex);
  pthread_mutex_destroy(&counter_mutex);
- pthread_mutex_destroy(&work_mutex);
  pthread_mutex_destroy(&type_cas_mutex);
  if (show_stat)
  pthread_mutex_destroy(&deepest_delta_mutex);
@@ -181,9 +176,6 @@ static void cleanup_thread(void)
 #define counter_lock()
 #define counter_unlock()

-#define work_lock()
-#

Where to report security vulnerabilities in git?

2015-08-21 Thread Guido Vranken
List,

I would like to report security vulnerabilities in git. Due to the
sensitive nature of security-impacting bugs I would like to know if
there's a dedicated e-mail address for this, so that the issues at
play can be patched prior to a coordinated public disclosure of the
germane exploitation details. I did find an older thread in the
archive addressing this question (
http://thread.gmane.org/gmane.comp.version-control.git/260328/ ), but
because I'm unsure if those e-mail addresses are still relevant, I'm
asking again.

Thanks.

Guido
--
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


Submodule, subtree, or something else?

2015-08-21 Thread Jānis Rukšāns
Hello,


First of all, I apologise for the wall of text that follows; obviously I
am bad at this.

My $DAYJOB is switching from Subversion to Git, primarily because of
it's distributed nature (we are scattered all across the globe), and the
ease of branching and merging.  One issue that has popped up is how to
manage code shared between multiple projects.

Our SVN setup used a shared repository for all projects, either using
externals for shared code, or, more often than not, simply merging the
code between projects as needed.  Ignoring the fact that merging with
SVN is somewhat cumbersome, overall it has worked quite well for us,
especially when combined with git-svn.

For external libraries that rarely change, submodules appear to be the
obvious choice when using Git.  On the other hand, I've found them
somewhat cumbersome to use, and subtree merging (either using git
subtree, or directly with git merge -s subtree) is closer to what we
were doing in SVN.  A major drawback of submodules in my opinion is the
inability to make a full clone from an existing one without having
access to the central repository, which is something I have to do from
time to time.

For internal libraries, the situation is even less clear.  For many of
these libraries, most of the development happens within the context of a
single project, with commits to main project being interleaved with
commits to the subproject(s), resulting in histories resembling:

 (using git submodule)

   A---B---S1---S2---C---S3
  ,´   ,´   ,´
 N---OPQ---R

 (using git subtree with --rejoin)

   A---B---N---O---M1---M2---Q---C---R---M3
  ///
 N'--O'---PQ'--R'

 (using merge -s subtree)

   A---B---M1---M2---C---M3
  ///
 N---OPQ---R

where A, B and C are changes to the main project, N, O, P, Q and R are
changes to library code, and Sn and Mn are submodule updates and merge
commits, respectively.

>From what I have gathered, submodules have issues with branching and
merging, therefore, unless I'm mistaken, submodules are kinda out of
question.  Of the remaining two options, merging directly results in a
nicer history, but requires making all changes to the library repo first
(although I am quite sure that a similar effect can be achieved with
plumbing, similarly to how git subtree split works), and is harder to
use than git subtree.  Also, all three options can result in the main
project history being cluttered with extra commits.

Lastly, there is a particularly painful 3rd party library that has an
enormous amount of local modifications that are never going to make it
upstream, essentially making it a fork, project specific changes that
are required for one project, but would break others, separate language
bindings that access the internals (often requiring bug fixes to be made
simultaneously to both), and, if that wasn't enough, it *requires*
several source files to be modified for each individual project that
uses it.  It's a complete mess, but we're stuck with it for the existing
projects, as switching to an alternative would be too time consuming.


To sum up, I'm looking for something that would let us share code
between multiple projects, allow for:

1) separate histories with relatively easy branching and merging

2) distributed workflow without having to set up a multiple repositories
everywhere (eg. work <-> home <-> laptop)

3) to work on the shared code within a project using it

4) inspection of the complete history

5) modifications that are not shared with other projects

and would not result in lots of clutter in the history.

Repository size is somewhat less of an issue, because each submodule has
to be checked out anyway.

Submodules let you have #3, and #1, #2 and #5 to a point, after which it
becomes a pain.  git subtree allows #1, #2, #3 and #4, and #5 with some
pain (?), but results in duplicate commits.  Using subtree merge
strategy directly gives everything except #3, but is harder to use than
submodules or subtree.

Are there any other options beside these three for sharing (or in some
cases, not sharing) common code between projects using Git, that would
address the above points better?  Or, alternatively, ways to work around
the drawbacks of the existing tools?

Lastly, I will be grateful for any suggestions about how to handle the
messy case described above better.

Thanks,
Jānis

--
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: Which branch(es) contain certain commits? (was Re: (unknown))

2015-08-21 Thread Junio C Hamano
Ivan Chernyavsky  writes:

> But now I had a look on the source and I can see that builtin/branch.c
> builds the list of references and prints them in a single place
> (print_ref_list()) so I will have to split that function into two in
> order to reuse existing functionality.
>
> Another problem is that builtin/branch.c currently does not use
> setup_revisions(), so I'll have to hook it there as well.
>
> Then, I assume, I'll need to use the initial ref_list (filled the same
> as for the current "list" case) to configure the rev_info structure
> after setup_revisions(), and start revision traversal.
>
> I'm not sure I've got it all right from the source in those few days,
> so I apologize in advance if it's stupid in some part or as a whole.

Heh, you say "problem" above, but I do not think it is a "problem"
per-se.  If you want to teach branch some preprocessing based on the
revision traversal API, you naturally need to call setup_revisions().

The outlined steps above all feel sensible; one thing you did not
mention is that you may probably have to clear object flags after
you are done with the initial "--grep" revision traversal, as some
features of branch may want to use the object flags (e.g. --merged
would use in_merge_bases()).  Other than that, all of it sounds
easily implementable.

Note that "branch --list", "tag --list" and "for-each-ref" are being
revamped to share more internal code.  If you want to pursue this,
you probably would want to build on top of that effort once it is
done.  That way, you may get "tag --grep=FIX123" for free.

> That said, do you think the goal is worth such changes?

That is a dangerous question.  As Duy already said,

> Probably because nobody is interested and steps up to do it. The lack
> of response to you mail is a sign.

apparently not many people thought it is worth; otherwise we would
already have such a feature.

If you are asking me personally, I'm sorry but I have to say no.

The reason why I personally do not think your "branch --grep=FIX123"
would be very useful to me is because I would imagine that I would
be interested in learning the exact commit that mentions FIX123 as
well as which branches contain it, if I had a need for such a
feature.

That is, it would inherently be two step process for me anyway, i.e.

 (1) I'd run "log -p --grep" to find which commits are about FIX123
 and check that what they did indeed make sense; and

 (2) I'd then run "branch --contains" to learn which ones are
 already up to date with respect to the fix.

Your "branch --grep=FIX123" that only tells me the names of branches
would have no use in that workflow, as it would not even give me an
indication that the request --grep=FIX123 found the right commit in
the first place.

--
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: Minor bug with help.autocorrect.

2015-08-21 Thread Junio C Hamano
Jeff King  writes:

> I think the plan is:
>
>   1. squelch the warning message from the config code; even if we change
>  the config format to pager.*.command, we will have to support
>  pager.* for historical reasons.
>
>   2. introduce pager.*.command so that "git foo_bar" can use
>  pager.foo_bar.command.
>
> We should do (1) in the near-term. We do not have to do (2) at all (and
> people with funny command names are simply out of luck), but it would be
> nice in the long run.

That sounds sensible.

> The patch from Tanay in $gmane/263888 accomplishes (1), but there was a
> minor cleanup needed (checking the individual bit in "flags", rather
> than the whole variable). Here it is with that fix:

Thanks; let's take a look.  I have a suspicion that it "accomplishes"
a lot more than (1) and may be discarding useful errors.

> diff --git a/config.c b/config.c
> index 9fd275f..dd0cb52 100644
> --- a/config.c
> +++ b/config.c
> @@ -1314,7 +1314,7 @@ static struct config_set_element 
> *configset_find_element(struct config_set *cs,
>* `key` may come from the user, so normalize it before using it
>* for querying entries from the hashmap.
>*/
> - ret = git_config_parse_key(key, &normalized_key, NULL);
> + ret = git_config_parse_key(key, &normalized_key, NULL, 
> CONFIG_ERROR_QUIET);

Hmm, I am not sure if this is correct, or it is trying to do things
at too low a level.

configset_add_value() calls configset_find_element().

A NULL return from find_element() could be because parse_key()
errored out due to bad name, or the key genuinely did not exist in
the hashmap, and the caller cannot tell.  So add_value() can end up
adding a new  pair under a bogus key, which is not a new
problem, but what makes me cautious is that it happens silently with
the updated code.

In fact, git_configset_add_file() uses git_config_from_file() with
configset_add_value() as its callback function, and the error that
is squelched with this CONFIG_ERROR_QUIET would be the only thing
that tells the user that the config file being read is malformed.

Right now, "git config" does not seem to use the full configset API
so nobody would notice, but still...

I wonder if alias_lookup() and check_pager_config(), two functions
that *know* that the string they have, cmd, could be invalid and
unusable key to give to the config API, should be doing an extra
effort (e.g. call parse_key() with QUIET option and refrain from
calling git_config_get_value()).  It feels that for existing callers
of parse_key(), not passing QUIET would be the right thing to do.

Of course, I am OK if git_config_get_value() and friends took the
QUIET flag and and passed it all the way down to parse_key(); that
would be a much more correct approach to address this issue (these
two callers do not have to effectively call parse_key() twice that
way), but at the same time, that would be a lot more involved
change.


--
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] contrib: teach completion about git-worktree options and arguments

2015-08-21 Thread Eric Sunshine
On Fri, Aug 21, 2015 at 4:49 PM, SZEDER Gábor  wrote:
> Quoting Junio C Hamano :
>> Eric Sunshine  writes:
>>> On Thu, Jul 23, 2015 at 4:49 PM, Eric Sunshine 
>>> wrote:
 Complete subcommands 'add' and 'prune', as well as their respective
 options --force, --detach, --dry-run, --verbose, and --expire. Also
 complete 'refname' in "git worktree add [-b ] 
 ".
>>>
>>> Ping[1]?
>>
>> Ping indeed?
>
> Yeah, right, sorry.  Non-subscribed occasional gmane-reader here amidst
> job hunting, so thanks for the ping.  And the re-ping...

Thanks for the review.

 +_git_worktree ()
 +{
 +   local subcommands='add prune'
 +   local subcommand="$(__git_find_on_cmdline "$subcommands")"
 +   local c=2 n=0 refpos=2
>
> A more descriptive variable name for 'n' would be great.

Indeed. I was planning on resubmitting with better variable names
(even if I didn't get any feedback)...

 +   if [ -z "$subcommand" ]; then
 +   __gitcomp "$subcommands"
 +   else
 +   case "$subcommand,$cur" in
 +   add,--*)
 +   __gitcomp "--force --detach"
>
> We usually don't offer '--force', because that option must be
> handled with care.

As a person who never uses git-completion (or git-prompt), I wasn't
aware of that, so thanks for the heads-up. I only installed completion
(and prompt) when I decided to work on this (and I don't think I've
used tab-completion since then).

 +   ;;
 +   add,*)
 +   while [ $c -lt $cword ]; do
 +   case "${words[c]}" in
 +   --*) ;;
 +   -[bB]) ((refpos++)) ;;
 +   *) ((n++)) ;;
 +   esac
 +   ((c++))
 +   done
 +   if [ $n -eq $refpos ]; then
>
> I suppose here you wanted to calculate where (i.e. at which word on
> the command line) we should offer refs and fall back to bash builtin
> filename completion otherwise.  It works well in the common cases,
> but:
>
>   - it doesn't offer refs after -b or -B

That was intentional since this is a new branch name, so it didn't
seem sensible to offer completion of existing refs. On the other hand,
it doesn't make much since to offer pathname completion either, but I
didn't see a better alternative. On reflection, I suppose ref
completion can make sense if the new branch name is going to be
similar to an existing one.

>   - it gets fooled by options to the git command, e.g. 'git
> --git-dir=.git worktree add ' offers refs instead of files,
> 'git --git-dir=.git worktree add ../some/path ' offers
> refs, etc.

This shortcoming could be addressed by computing relative to the
subcommand-index as your version does, correct?

I don't have enough background with the (git-specific) completion
facility to be able to judge if this patch and approach has merit and
ought to be pursued further, or if it would be better to drop in favor
of (some version of) your patch. I don't care strongly, and am fine
with dropping this patch if it's approach is suboptimal.

 +   __gitcomp_nl "$(__git_refs)"
 +   fi
 +   ;;
 +   prune,--*)
 +   __gitcomp "--dry-run --verbose --expire"
 +   ;;
 +   esac
 +   fi
 +}
 +
--
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 3z/3] log: make '-p' imply '-m --cc'

2015-08-21 Thread Junio C Hamano
Junio C Hamano  writes:

> The latter was inspired by a recent discussion, most notably
>
>http://thread.gmane.org/gmane.comp.version-control.git/273937/focus=273988
>
> but implements it with a much less UI impact.  Tweaking "git log -p"
> has a lot of fallout---interested parties can try it out and how two
> tests in t4xxx series break.

Just for the record, here is what I did before deciding that the
idea of turning '-p' into '--cc -m' is not good and instead did the
"'--cc' should show the patch without '-p' and '-m'" that is the
real [3/3].  The attached patch replaces 3/3, showss what happens if
you tweak 'log -p' to imply '-m --cc'"; the change of behaviours is
illustrated by the updated tests.

Many are good-looking, and some others are questionable.

 * "log -G -p" and "log -S -p" that silently turns
   "-p" into "-m --cc" shows merges that changed the occurrences of
   , but if the merge is a trivial textual merge, the change
   itself is not seen (as we are doing "--cc").  This looks very
   questionable.

 * Similarly, "log -p --stat" shows the diffstat against the first
   parent for a merge but does not show the patch text, as "--cc" is
   in effect, for a trivial textual merge.  This looks strange.

 * Even though I very much do like the fact that we see _something_
   in the output for a merge commit, "log --patch-with-stat" that
   outputs a "patch" that cannot be grokked by "git apply" feels
   wrong.

All of the above led me to say "when the user explicitly asks --cc,
show the merges that way, otherwise keeping the 'merges are by
default ignored' is the right thing".


diff --git a/builtin/log.c b/builtin/log.c
index 519f170..1a77804 100644
--- a/builtin/log.c
+++ b/builtin/log.c
@@ -633,6 +633,14 @@ static void log_setup_revisions_tweak(struct rev_info *rev,
rev->prune_data.nr == 1)
DIFF_OPT_SET(&rev->diffopt, FOLLOW_RENAMES);
 
+   /* Turn -p without -m to --cc -p -m */
+   if (rev->ignore_merges && !rev->combine_merges &&
+   (rev->diffopt.output_format & DIFF_FORMAT_PATCH)) {
+   rev->ignore_merges = 0;
+   rev->combine_merges = 1;
+   rev->dense_combined_merges = 1;
+   }
+
/* Turn --cc/-c into -p --cc/-c when -p was not given */
if (!rev->diffopt.output_format && rev->combine_merges)
rev->diffopt.output_format = DIFF_FORMAT_PATCH;
diff --git a/t/t4013/diff.log_--patch-with-stat_--summary_master_--_dir_ 
b/t/t4013/diff.log_--patch-with-stat_--summary_master_--_dir_
index a18f147..04f4eee 100644
--- a/t/t4013/diff.log_--patch-with-stat_--summary_master_--_dir_
+++ b/t/t4013/diff.log_--patch-with-stat_--summary_master_--_dir_
@@ -6,6 +6,23 @@ Date:   Mon Jun 26 00:04:00 2006 +
 
 Merge branch 'side'
 
+ dir/sub | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --cc dir/sub
+index cead32e,7289e35..992913c
+--- a/dir/sub
 b/dir/sub
+@@@ -1,6 -1,4 +1,8 @@@
+  A
+  B
+ +C
+ +D
+ +E
+ +F
++ 1
++ 2
+
 commit c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a
 Author: A U Thor 
 Date:   Mon Jun 26 00:03:00 2006 +
diff --git a/t/t4013/diff.log_--patch-with-stat_master 
b/t/t4013/diff.log_--patch-with-stat_master
index ae425c4..ec4b1b9 100644
--- a/t/t4013/diff.log_--patch-with-stat_master
+++ b/t/t4013/diff.log_--patch-with-stat_master
@@ -6,6 +6,38 @@ Date:   Mon Jun 26 00:04:00 2006 +
 
 Merge branch 'side'
 
+ dir/sub | 2 ++
+ file0   | 3 +++
+ 2 files changed, 5 insertions(+)
+
+diff --cc dir/sub
+index cead32e,7289e35..992913c
+--- a/dir/sub
 b/dir/sub
+@@@ -1,6 -1,4 +1,8 @@@
+  A
+  B
+ +C
+ +D
+ +E
+ +F
++ 1
++ 2
+diff --cc file0
+index b414108,f4615da..10a8a9f
+--- a/file0
 b/file0
+@@@ -1,6 -1,6 +1,9 @@@
+  1
+  2
+  3
+ +4
+ +5
+ +6
++ A
++ B
++ C
+
 commit c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a
 Author: A U Thor 
 Date:   Mon Jun 26 00:03:00 2006 +
diff --git a/t/t4013/diff.log_--patch-with-stat_master_--_dir_ 
b/t/t4013/diff.log_--patch-with-stat_master_--_dir_
index d5207ca..d3be9a2 100644
--- a/t/t4013/diff.log_--patch-with-stat_master_--_dir_
+++ b/t/t4013/diff.log_--patch-with-stat_master_--_dir_
@@ -6,6 +6,23 @@ Date:   Mon Jun 26 00:04:00 2006 +
 
 Merge branch 'side'
 
+ dir/sub | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --cc dir/sub
+index cead32e,7289e35..992913c
+--- a/dir/sub
 b/dir/sub
+@@@ -1,6 -1,4 +1,8 @@@
+  A
+  B
+ +C
+ +D
+ +E
+ +F
++ 1
++ 2
+
 commit c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a
 Author: A U Thor 
 Date:   Mon Jun 26 00:03:00 2006 +
diff --git a/t/t4013/diff.log_--root_--patch-with-stat_--summary_master 
b/t/t4013/diff.log_--root_--patch-with-stat_--summary_master
index dffc09d..a6aa60a 100644
--- a/t/t4013/diff.log_--root_--patch-with-stat_--summary_master
+++ b/t/t4013/diff.log_--root_--patch-with-stat_--summary_master
@@ -6,6 +6,38 @@ Date:   Mon Jun 26 00:04:00 2006 +
 
 Merge branch 'side'
 
+ dir/sub | 2 ++
+ file0   | 3 +++
+ 2 files changed, 5 insertions(+)
+
+diff --

Which branch(es) contain certain commits? (was Re: (unknown))

2015-08-21 Thread Ivan Chernyavsky


17.08.2015, 20:49, "Junio C Hamano" :
>  Duy Nguyen  writes:
>
>>   On Wed, Aug 5, 2015 at 7:47 PM, Ivan Chernyavsky  
>> wrote:
>
>  That is a dangeous thought. I'd understand if it were internally
>  two step process, i.e. (1) the first pass finds commits that hits
>  the --grep criteria and then (2) the second pass does "--contains"
>  for all the hits found in the first pass using existing code, but
>  still, this operation is bound to dig all the way through the root
>  of the history when asked to find something that does not exist.

My intention was to use existing git-branch filters such as -a or -r and 
pattern to limit the scope, then apply --grep machinery.

But now I had a look on the source and I can see that builtin/branch.c builds 
the list of references and prints them in a single place (print_ref_list()) so 
I will have to split that function into two in order to reuse existing 
functionality.

Another problem is that builtin/branch.c currently does not use 
setup_revisions(), so I'll have to hook it there as well.

Then, I assume, I'll need to use the initial ref_list (filled the same as for 
the current "list" case) to configure the rev_info structure after 
setup_revisions(), and start revision traversal.

I'm not sure I've got it all right from the source in those few days, so I 
apologize in advance if it's stupid in some part or as a whole.

That said, do you think the goal is worth such changes? Seems like git-branch 
currently has it's own way of doing things and I'm trying to teach it to use 
git-rev-list's.

Maybe it is more reasonable to add an option to "git log --all --source 
--grep=..." to print *all* branch tips which are reachable from the found 
commits, not only the first one encountered? E.g. --decorate-all or 
--source-all?

>  You should at least feed all --contains to a single invocation of
>  "git branch". They are designed to be OR'ed together.


Yep thanks I overlooked that. In my repository, this takes 40 seconds instead 
of 2 minutes 30 seconds for my construct.

-- 
  Ivan
--
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 2/3] run-commands: add an async queue processor

2015-08-21 Thread Stefan Beller
On Fri, Aug 21, 2015 at 1:47 PM, Junio C Hamano  wrote:
>
> I do not think we are on the same wavelength.  What I meant was to
> do this:
>
> aq = xmalloc(...);
> set up _everything_ in aq and make it a consistent state;
> /* aq->first and aq->last are part of _everything_ in aq */
> for (many times)
> pthread_create(...);
>
> /* No aq->first = aq->last = NULL assignment here */
>
> instead of
>
> aq = xmalloc(...);
> set up part of aq;
> for (many times)
> pthread_create(...);
> belatedly initialize aq->first and aq->last and finally
> aq becomes a consistent state.
>
> which is what we see above.  The latter works _only_ because the
> threads created are blocked waiting on aq->workingcount which is
> initialized to block before threads are created to run dispatch,
> and one of the early things dispatch does is to try acquiring that
> semaphore to block before accessing aq->first and aq->last.

I see your point and it makes sense to me as it makes the
mental memory model cleaner

I viewed the methods as atomic units (you would not call add_task
before the constructor has finished, so no harm there. And a dispatcher
in the pthread would just block on the `workingcount` semaphore as the
semaphores are the main inter thread communication. I viewed the queue
as just a secondary thing to distribute the work load.
--
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


[PoC PATCH] completion: support 'git worktree'

2015-08-21 Thread SZEDER Gábor
Signed-off-by: SZEDER Gábor 
---

> I wrote a completion function for 'git worktree' as well, turns out a week
> or two before you posted this, but I never submitted it as it was way too
> convoluted.  Anyway, will send it in reply to this, just for reference.

And here it is.
>From the number of indentation levels and comment lines you can see why
I haven't submitted this patch yet :)

OTOH it offers refs for -b and -B, and there are only fairly narrow
corner cases when 'git --options' can fool it (but that's a general
issue with __git_find_on_cmdline(), I wouldn't go into that).

 contrib/completion/git-completion.bash | 59 ++
 1 file changed, 59 insertions(+)

diff --git a/contrib/completion/git-completion.bash 
b/contrib/completion/git-completion.bash
index c97c648d7e..20a17e2c50 100644
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -2564,6 +2564,65 @@ _git_whatchanged ()
_git_log
 }
 
+_git_worktree ()
+{
+   local subcommand subcommand_idx sc c=1
+   local subcommands="add prune"
+
+   while [ $c -lt $cword ] && [ -z "$subcommand" ]; do
+   for sc in $subcommands; do
+   if [ "$sc" = "${words[c]}" ]; then
+   subcommand=$sc
+   subcommand_idx=$c
+   break
+   fi
+   done
+   ((c++))
+   done
+
+   case "$subcommand,$cur" in
+   ,*)
+   __gitcomp "$subcommands"
+   ;;
+   add,--*)
+   __gitcomp "--detach"
+   ;;
+   add,*)
+   case "$prev" in
+   -b|-B)
+   __gitcomp_nl "$(__git_refs)"
+   ;;
+   -*) # $prev is an option without argument: have to complete
+   # the path for the new worktree, fall back to bash
+   # filename completion
+   ;;
+   *)  # $prev is not an option, so it must be either the
+   # 'add' subcommand, an argument of an option (e.g.
+   # branch for -b|-B), or the path for the new worktree
+   if [ $cword -eq $((subcommand_idx+1)) ]; then
+   # right after the 'add' subcommand, have to
+   # complete the path
+   :
+   else
+   case "${words[cword-2]}" in
+   -b|-B)  # after '-b ', have to complete
+   # the path
+   ;;
+   *)  # after the path, have to complete the
+   # branch to be checked out
+   __gitcomp_nl "$(__git_refs)"
+   ;;
+   esac
+   fi
+   ;;
+   esac
+   ;;
+   prune,--*)
+   __gitcomp "--dry-run --verbose --expire"
+   ;;
+   esac
+}
+
 __git_main ()
 {
local i c=1 command __git_dir
-- 
2.5.0.418.gdd37a9b

--
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] contrib: teach completion about git-worktree options and arguments

2015-08-21 Thread SZEDER Gábor


Quoting Junio C Hamano :


Eric Sunshine  writes:

On Thu, Jul 23, 2015 at 4:49 PM, Eric Sunshine  
 wrote:

Complete subcommands 'add' and 'prune', as well as their respective
options --force, --detach, --dry-run, --verbose, and --expire. Also
complete 'refname' in "git worktree add [-b ] 
".


Ping[1]?

[1]: http://article.gmane.org/gmane.comp.version-control.git/274526


Ping indeed?



Yeah, right, sorry.  Non-subscribed occasional gmane-reader here amidst
job hunting, so thanks for the ping.  And the re-ping...


Signed-off-by: Eric Sunshine 
---

This is RFC since this is my first foray into the Git completion script,
and there are likely better and more idiomatic ways to accomplish this.


Using __git_find_on_cmdline() to find subcommands and case
"$subcommand,$cur" to limit the number of nested case statements is as
idiomatic as you can get in the completion script.

And I hear you, that " first,  second" syntax makes it way
too complicated, especially since they can follow '-b '.
I wrote a completion function for 'git worktree' as well, turns out a week
or two before you posted this, but I never submitted it as it was way too
convoluted.  Anyway, will send it in reply to this, just for reference.



 contrib/completion/git-completion.bash | 32  


 1 file changed, 32 insertions(+)

diff --git a/contrib/completion/git-completion.bash  
b/contrib/completion/git-completion.bash

index c97c648..07c34ef 100644
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -2564,6 +2564,38 @@ _git_whatchanged ()
_git_log
 }

+_git_worktree ()
+{
+   local subcommands='add prune'
+   local subcommand="$(__git_find_on_cmdline "$subcommands")"
+   local c=2 n=0 refpos=2


A more descriptive variable name for 'n' would be great.


+   if [ -z "$subcommand" ]; then
+   __gitcomp "$subcommands"
+   else
+   case "$subcommand,$cur" in
+   add,--*)
+   __gitcomp "--force --detach"


We usually don't offer '--force', because that option must be
handled with care.


+   ;;
+   add,*)
+   while [ $c -lt $cword ]; do
+   case "${words[c]}" in
+   --*) ;;
+   -[bB]) ((refpos++)) ;;
+   *) ((n++)) ;;
+   esac
+   ((c++))
+   done
+   if [ $n -eq $refpos ]; then


I suppose here you wanted to calculate where (i.e. at which word on
the command line) we should offer refs and fall back to bash builtin
filename completion otherwise.  It works well in the common cases,
but:

  - it doesn't offer refs after -b or -B

  - it gets fooled by options to the git command, e.g. 'git
--git-dir=.git worktree add ' offers refs instead of files,
'git --git-dir=.git worktree add ../some/path ' offers
refs, etc.


+   __gitcomp_nl "$(__git_refs)"
+   fi
+   ;;
+   prune,--*)
+   __gitcomp "--dry-run --verbose --expire"
+   ;;
+   esac
+   fi
+}
+
 __git_main ()
 {
local i c=1 command __git_dir
--
2.5.0.rc3.407.g68aafd0



--
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 2/3] run-commands: add an async queue processor

2015-08-21 Thread Junio C Hamano
Stefan Beller  writes:

>>> +struct task_queue *create_task_queue(unsigned max_threads)
>>> +{
>>> + struct task_queue *aq = xmalloc(sizeof(*aq));
>>> +
>>> +#ifndef NO_PTHREADS
>>> + int i;
>>> + if (!max_threads)
>>> + aq->max_threads = online_cpus();
>>> + else
>>> + aq->max_threads = max_threads;
>>> +
>>> + sem_init(&aq->mutex, 0, 1);
>>> + sem_init(&aq->workingcount, 0, 0);
>>> + sem_init(&aq->freecount, 0, aq->max_threads);
>>> + aq->threads = xmalloc(aq->max_threads * sizeof(pthread_t));
>>> +
>>> + for (i = 0; i < aq->max_threads; i++)
>>> + pthread_create(&aq->threads[i], 0, &dispatcher, aq);
>>> +
>>> + aq->first = NULL;
>>> + aq->last = NULL;
>>
>>
>> Shouldn't these be initialized before letting threads call into
>> dispatcher?  The workingcount semaphore that is initialized to 0 may
>> prevent them from peeking into these pointers and barfing, but still...
>
> They are initialized to NULL as the empty queue doesn't need a
> container element.
> Do we do queues in another way usually?

I do not think we are on the same wavelength.  What I meant was to
do this:

aq = xmalloc(...);
set up _everything_ in aq and make it a consistent state;
/* aq->first and aq->last are part of _everything_ in aq */
for (many times)
pthread_create(...);

/* No aq->first = aq->last = NULL assignment here */

instead of

aq = xmalloc(...);
set up part of aq;
for (many times)
pthread_create(...);
belatedly initialize aq->first and aq->last and finally
aq becomes a consistent state.

which is what we see above.  The latter works _only_ because the
threads created are blocked waiting on aq->workingcount which is
initialized to block before threads are created to run dispatch,
and one of the early things dispatch does is to try acquiring that
semaphore to block before accessing aq->first and aq->last.
--
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 2/3] run-commands: add an async queue processor

2015-08-21 Thread Junio C Hamano
Jeff King  writes:

> On Fri, Aug 21, 2015 at 12:05:13PM -0700, Junio C Hamano wrote:
>
>> The primary reason I suspect is because you sent to a wrong set of
>> people.  Submodule folks have largely been working in the scripted
>> ones, and may not necessarily be the ones who are most familiar with
>> the run-command infrastructure.
>> 
>> "shortlog --no-merges" tells me that the obvious suspects are j6t
>> and peff.
>
> No good deed goes unpunished. ;)
>
> Before even looking at the implementation, my first question would be
> whether this pattern is applicable in several places in git (i.e., is it
> worth the extra complexity of abstracting out in the first place). I
> think there are a few task-queue patterns already in git; for example
> the delta search in pack-objects. Is the interface given here sufficient
> to convert pack-objects? Is the result nicer to read? Is it as
> efficient?
>
> We do not need to convert all possible call-sites to the new abstracted
> code at once. But I find that converting at least _one_ is a good litmus
> test to confirm that a new interface is generally useful.

Ah, thanks for saying this.  I recall saying something similar
earlier and totally agree with you.
--
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


Urgent, Dear Invited Author,

2015-08-21 Thread Olga Nikolova
Dear Invited Author,

You have 6 days until August 25 for your Invited Paper in the WSEAS Conferences 
in Seoul, South Korea. 
We have just upgraded the role of Invited Speakers (see below). The extended 
version of the accepted papers will be published in our collaborating 44 ISI 
Journals.

If August 25 is too early for you to upload your invited paper in our 
conferences in Seoul, South Korea, you must know
that we have also conferences in Michigan State University, East Lansing, MI, 
USA, September 20-22, 2015
and we would like to invite you to come as Invited Speaker to present an 
Invited Paper. 

So, select one of our conferences in Seouls, Korea and/or Michigan State 
University, USA via http://www.wseas.org   
and upload your invited paper until until August 25 for Seouls, Korea and 
September 8, 2015  for Michigan State University, East Lansing, MI
(Maximum 10 pages. Format see the web page of the conference)

Michigan State University is co-sponsor and co-organizer and the events will be 
held inside the buildings of the University

This is really a unique opportunity with publication in our ISI (indexed by 
Thomson Reuters) Journals
You can publish your paper in one of our 44 ISI (indexed by Thomson Reuters) 
Journals 
Upload your invited paper now by selecting the most appropriate conference via 
www.wseas.org

Invited Authors can also have an Interview in our channel (See some recent 
interviews of our Invited and Plenary Speakers
in the third column of our Web Portal under the "Bulletin Board").

You can follow us in Facebook: www.facebook.con/Wseas and you can see several 
photos and video from our recent conferences here: wseas.org

The ISI Journals (with Impact Factor from Thomson Reuters) that publish the 
accepted papers from WSEAS Conferences are now 44.  
Several ISI Journals sent us proposals for collaboration in November and 
December of 2014, 
so the number of ISI Journals that publish the accepted papers of WSEAS 
conferences are now 44.
Each journal will host approximately 10-15 papers from WSEAS Conferences.

You can upload your Invited Paper if you fill-in in the field "Session": 
invited-by-olga-nikolova-...@vger.kernel.org
Do not send papers by email. 

Invited Authors have
==
a) Invitation for Additional publication of the extended version
in ISI Journals and Positive Recommendation from an Editor for publication in 
an ISI Journal. 
You select the Journal where you can publish the extended version of your paper.

b) Priority in the conference program

c) Double time for presentation (not 15 minutes as the regular papers, but 30 
minutes)

d) Invited Papers are noted explicitly in the conference program as Invited 
Papers

e) Invited Authors can be included in the Program Committee of our future 
conferences of 2015

f) Invitation for Co-organizing a future WSEAS Event.

g) 20 additional days to upload their invited papers


All the authors have

Publication in the Conference proceedings and distribution in the conference 10 
Books + 1 CD-ROM (total of the 10 books)

You must upload your Invited Paper only via the particular conference web site 
and you must declare in the 
Field of Special Session this code:  
invited-by-olga-nikolova-...@vger.kernel.org (in order to consider your paper 
as Invited paper). 
Do not send papers by email.



Remarks
-
1)  Invited Authors represent only a 3-5% of our authors,
see for example the papers with Italics here:  
http://www.wseas.org/main/conferences/2014/Salerno/Program.pdf )

2) Invited Authors are selected very carefully according their recent 
publications and citations and
they must fit to the topics of the conference.

3) If you want, you can give also an Interview in our Web Channel during the 
days of the conference.
Please, check:  http://wseas.org/cms.action?id=8322

Do not hesitate to contact me for more questions


Indexing
===
ISI (Thomson Reuters), ELSEVIER, SCOPUS, ACM -  Association for Computing 
Machinery, Zentralblatt MATH, British Library, EBSCO, SWETS, EMBASE, CAS - 
American Chemical Society, CiteSeerx, Cabell Publishing, Electronic Journals, 
Library, SAO/NASA Astrophysics Data System
EI Compendex, Engineering Village, CSA Cambridge Scientific Abstracts, DoPP, 
GEOBASE, Biobase, American Mathematical Society (AMS), Inspec - The IET, 
Ulrich's International Periodicals Directory

The ISI Journals (with Impact Factor from Thomson Reuters) that publish the 
accepted papers from WSEAS Conferences are now 44.  Several ISI Journals sent 
us proposals for collaboration in November and December of 2014, so the number 
of ISI Journals that publish the accepted papers of WSEAS conferences are now 
33.
Each journal will host approximately 10-15 papers from WSEAS Conferences in 
Michigan State University, East Lansing, MI, September 20-22, 2015 

Best Regards
(more details:  publish...@wseas.org )

Dr. Olga Nikolova
WSEAS Editorial Office
www.wseas.org
publish...@w

Re: [WIP/PATCH 3/3] submodule: helper to run foreach in parallel

2015-08-21 Thread Stefan Beller
On Fri, Aug 21, 2015 at 12:23 PM, Junio C Hamano  wrote:
> Stefan Beller  writes:
>
>> +struct submodule_args {
>> + const char *name;
>> + const char *path;
>> + const char *sha1;
>> + const char *toplevel;
>> + const char *prefix;
>> + const char **cmd;
>> + struct submodule_output *out;
>> + sem_t *mutex;
>> +};
>
> I do not see what submodule_output looks like in the patch, but I
> guess you are capturing _all_ output from a task and emitting
> everything at the end, after the task is done?

It was a leftover and will be removed. Sorry for wasting your time.
So jrnieder and me had a discussion on how to do get the output right.

And we had 2 designs:

1) The worker thread acquires a mutex to be allowed to write to
  stdout. This makes early output easy for each thread in case of
  error messages. It also requires less resources than 2).
  Also the expected code complexity is lower as the decisions
  are made locally.

2) Have a single handler which deals with all output of all tasks.
  This handler would `select` on a huge number of pipes from
  all the tasks, (so we would require a lot of pipes). And this central
  handler (which would be submodule_output in this case) would
  take care of having no intermingled racy output from tasks, with
  prefixes and all bells and whistles. This handler could also
  give a progress meter (300 out of 500 submodules updated already)
  for all threads, or when the last task is running switch to piping
  the output of that task to stdout in real time, so you'd get progress
  of the last task as you're already used to.

The outcome of the discussion was to split the worker pool/load
distribution from the output handling in any case as there is no need
to couple them. In my very first designs I had the output handling
as part of the asynchronous worker pool.

This RFC implements 1), that's why there is only the mutex.
I plan on enhancing this to let the last task output in real time (no buffering)
as well as another counter "task n/m completed" after each task
is done.

>
> I have to wonder if that is what people would expect and more
> importantly if that is the most useful.  I am sympathetic to the
> desire to avoid the output totally mixed up from different processes
> emitting things in an uncoordinated manner, and "slurp everything
> and then show everything in one go" is certainly _one_ way to do so,
> but early feedback also counts.  Besides, because the order in which
> tasks are dispatched and completed is unpredictable, you cannot
> expect a machine parseable output _without_ assuming some help from
> the command invoked by each task (e.g. by prefixing the task's output
> with some string that identifies which submodule the output is about).

I was very focused on the "submodule foreach" output, which (in case of
no -q given), displays a

"Entering %s"

as the first line for each finished task. I suspect that is not enough to
make it a good machine parseable output. So I will prefix each
line with a running number of the task. Maybe like this:

  [001/500] Entering 'foo/bar'
  [001/500] Here goes the text for task foo/bar
  [001/500] Here goes another text for task foo/bar
  [002/500] Entering 'foo/baz'
  [002/500] Here goes the text for task foo/baz
  [002/500] Here goes another text for task foo/bar
  [003/500] Entering 'foo/bla'
  ...

This will make the output for each task distinguishable from
other tasks as well offering some sort of progress meter.
(The fewer submodules you have the less fine grained
the progress bar becomes)

Jonathan suggested to add a capability to the git protocol for a
machine readable progress meter in another channel. so we do not
need to parse the current output Counting/Compressing/Transfer/etc

>
> Once you assume that the command is _aware_ that it needs to help
> the foreach-parallel infrastructure so that the user can sift their
> collective outputs to make sense of them, wouldn't a line-buffered
> intermixing also acceptable, and wouldn't it be a much lower impact
> approach to solve the same problem?
--
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 2/3] run-commands: add an async queue processor

2015-08-21 Thread Stefan Beller
On Fri, Aug 21, 2015 at 12:51 PM, Jeff King  wrote:
> On Fri, Aug 21, 2015 at 12:48:23PM -0700, Stefan Beller wrote:
>
>> > Before even looking at the implementation, my first question would be
>> > whether this pattern is applicable in several places in git (i.e., is it
>> > worth the extra complexity of abstracting out in the first place). I
>> > think there are a few task-queue patterns already in git; for example
>> > the delta search in pack-objects. Is the interface given here sufficient
>> > to convert pack-objects? Is the result nicer to read? Is it as
>> > efficient?
>> >
>> > We do not need to convert all possible call-sites to the new abstracted
>> > code at once. But I find that converting at least _one_ is a good litmus
>> > test to confirm that a new interface is generally useful.
>>
>> Ok, I'll head off to convert one place.
>
> Thanks. By the way, reading over what I wrote, it sounds a little
> harsher than I meant.

It did not sound harsh at all. I was just reading an internal mailing list,
which cites over generalizing as a very bad practice worse than
premature optimization, so I totally understand your concern and
agree.

> It is not "if you do not convert an existing site,
> we cannot accept a new interface, period". But I would like at least
> some explanation as an alternative, like "I'm pretty sure we can convert
> site X to this, but it is not a good time to do so now because of Y".
> Where "Y" might be "we need to do this other refactoring work first", or
> "it would be disruptive to other work in the area".
>
> -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: [RFC PATCH 2/3] run-commands: add an async queue processor

2015-08-21 Thread Jeff King
On Fri, Aug 21, 2015 at 12:48:23PM -0700, Stefan Beller wrote:

> > Before even looking at the implementation, my first question would be
> > whether this pattern is applicable in several places in git (i.e., is it
> > worth the extra complexity of abstracting out in the first place). I
> > think there are a few task-queue patterns already in git; for example
> > the delta search in pack-objects. Is the interface given here sufficient
> > to convert pack-objects? Is the result nicer to read? Is it as
> > efficient?
> >
> > We do not need to convert all possible call-sites to the new abstracted
> > code at once. But I find that converting at least _one_ is a good litmus
> > test to confirm that a new interface is generally useful.
> 
> Ok, I'll head off to convert one place.

Thanks. By the way, reading over what I wrote, it sounds a little
harsher than I meant. It is not "if you do not convert an existing site,
we cannot accept a new interface, period". But I would like at least
some explanation as an alternative, like "I'm pretty sure we can convert
site X to this, but it is not a good time to do so now because of Y".
Where "Y" might be "we need to do this other refactoring work first", or
"it would be disruptive to other work in the area".

-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: [RFC PATCH 2/3] run-commands: add an async queue processor

2015-08-21 Thread Stefan Beller
On Fri, Aug 21, 2015 at 12:44 PM, Jeff King  wrote:
> On Fri, Aug 21, 2015 at 12:05:13PM -0700, Junio C Hamano wrote:
>
>> The primary reason I suspect is because you sent to a wrong set of
>> people.  Submodule folks have largely been working in the scripted
>> ones, and may not necessarily be the ones who are most familiar with
>> the run-command infrastructure.
>>
>> "shortlog --no-merges" tells me that the obvious suspects are j6t
>> and peff.
>
> No good deed goes unpunished. ;)
>
> Before even looking at the implementation, my first question would be
> whether this pattern is applicable in several places in git (i.e., is it
> worth the extra complexity of abstracting out in the first place). I
> think there are a few task-queue patterns already in git; for example
> the delta search in pack-objects. Is the interface given here sufficient
> to convert pack-objects? Is the result nicer to read? Is it as
> efficient?
>
> We do not need to convert all possible call-sites to the new abstracted
> code at once. But I find that converting at least _one_ is a good litmus
> test to confirm that a new interface is generally useful.

Ok, I'll head off to convert one place.

>
> -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: [RFC PATCH 2/3] run-commands: add an async queue processor

2015-08-21 Thread Stefan Beller
On Fri, Aug 21, 2015 at 12:05 PM, Junio C Hamano  wrote:
> Stefan Beller  writes:
>
>> This adds functionality to do work in parallel.
>>
>> The whole life cycle of such a thread pool would look like
>>
>> struct task_queue * tq = create_task_queue(32); // no of threads
>> for (...)
>> add_task(tq, process_one_item_function, item); // non blocking
>> ...
>> int ret = finish_task_queue(tq); // blocks until all tasks are done
>> if (!tq)
>> die ("Not all items were be processed");
>>
>> The caller must take care of handling the output.
>>
>> Signed-off-by: Stefan Beller 
>> ---
>>
>> I sent this a while ago to the list, no comments on it :(
>
> The primary reason I suspect is because you sent to a wrong set of
> people.  Submodule folks have largely been working in the scripted
> ones, and may not necessarily be the ones who are most familiar with
> the run-command infrastructure.
>
> "shortlog --no-merges" tells me that the obvious suspects are j6t
> and peff.

noted.

>
>> The core functionality stayed the same, but I hope to improved naming and
>> location of the code.
>>
>> The WIP is only for the NO_PTHREADS case.
>
>>  run-command.c | 212 
>> ++
>>  run-command.h |  30 +
>>  2 files changed, 230 insertions(+), 12 deletions(-)
>>
>> diff --git a/run-command.c b/run-command.c
>> index 28e1d55..4029011 100644
>> --- a/run-command.c
>> +++ b/run-command.c
>> @@ -4,6 +4,21 @@
>>  #include "sigchain.h"
>>  #include "argv-array.h"
>>
>> +#ifdef NO_PTHREADS
>> +
>> +#else
>> +
>> +#include "thread-utils.h"
>> +
>> +#include 
>> +#include 
>> +#include 
>> +#include 
>> +
>> +#endif
>> +
>> +#include "git-compat-util.h"
>> +
>
> This goes against the way we have been organizing the header files.
>
> http://thread.gmane.org/gmane.comp.version-control.git/276241/focus=276265

ok
>
>> @@ -668,6 +683,22 @@ int git_atexit(void (*handler)(void))
>>
>>  #endif
>>
>> +void setup_main_thread()
>
> void setup_main_thread(void)
>
>> @@ -852,3 +872,171 @@ int capture_command(struct child_process *cmd, struct 
>> strbuf *buf, size_t hint)
>>   close(cmd->out);
>>   return finish_command(cmd);
>>  }
>> +
>> +#ifndef NO_PTHREADS
>> +struct job_list {
>> + int (*fct)(struct task_queue *aq, void *task);
>> + void *task;
>> + struct job_list *next;
>> +};
>> +#endif
>> +
>> +struct task_queue {
>> +#ifndef NO_PTHREADS
>> + /*
>> +  * To avoid deadlocks always aquire the semaphores with lowest priority
>
> acquire.
>
>> +  * first, priorites are in descending order as listed.
>> +  *
>> +  * The `mutex` is a general purpose lock for modifying data in the 
>> async
>> +  * queue, such as adding a new task or adding a return value from
>> +  * an already run task.
>> +  *
>> +  * `workingcount` and `freecount` are opposing semaphores, the sum of
>> +  * their values should equal `max_threads` at any time while the 
>> `mutex`
>> +  * is available.
>> +  */
>> + sem_t mutex;
>> + sem_t workingcount;
>> + sem_t freecount;
>> +
>> + pthread_t *threads;
>> + unsigned max_threads;
>> +
>> + struct job_list *first;
>> + struct job_list *last;
>> +#endif
>> + int early_return;
>> +};
>> +
>> +#ifndef NO_PTHREADS
>> +
>> +static void get_task(struct task_queue *aq,
>> +  int (**fct)(struct task_queue *aq, void *task),
>> +  void **task,
>> +  int *early_return)
>> +{
>> + struct job_list *job;
>> +
>> + sem_wait(&aq->workingcount);
>> + sem_wait(&aq->mutex);
>> +
>> + if (!aq->first)
>> + die("BUG: internal error with dequeuing jobs for threads");
>> + job = aq->first;
>> + *fct = job->fct;
>> + *task = job->task;
>> + aq->early_return |= *early_return;
>> + *early_return = aq->early_return;
>> + aq->first = job->next;
>> + if (!aq->first)
>> + aq->last = NULL;
>> +
>> + sem_post(&aq->freecount);
>> + sem_post(&aq->mutex);
>> +
>> + free(job);
>> +}
>> +
>> +static void* dispatcher(void *args)
>
> static void *dispatcher()
>
>> +{
>> + void *task;
>> + int (*fct)(struct task_queue *aq, void *data);
>
> s/data/task/?
>
>> + int early_return = 0;
>> + struct task_queue *aq = args;
>> +
>> + get_task(aq, &fct, &task, &early_return);
>> + while (fct || early_return != 0) {
>> + early_return = fct(aq, task);
>> + get_task(aq, &fct, &task, &early_return);
>> + }
>
> If the func said "we are done, you may stop dispatching now", do you
> still want to do another get_task()?

This question shows me I messed up readability of this. `get_task` both gets
a new task as well as taking the value from early_return writing it to
aq->early_return,
such that other threads are notified.

Maybe I should do that explicitely here and not get the new task.

>
>> + pthread_exit(0);
>

Re: [RFC PATCH 2/3] run-commands: add an async queue processor

2015-08-21 Thread Jeff King
On Fri, Aug 21, 2015 at 12:05:13PM -0700, Junio C Hamano wrote:

> The primary reason I suspect is because you sent to a wrong set of
> people.  Submodule folks have largely been working in the scripted
> ones, and may not necessarily be the ones who are most familiar with
> the run-command infrastructure.
> 
> "shortlog --no-merges" tells me that the obvious suspects are j6t
> and peff.

No good deed goes unpunished. ;)

Before even looking at the implementation, my first question would be
whether this pattern is applicable in several places in git (i.e., is it
worth the extra complexity of abstracting out in the first place). I
think there are a few task-queue patterns already in git; for example
the delta search in pack-objects. Is the interface given here sufficient
to convert pack-objects? Is the result nicer to read? Is it as
efficient?

We do not need to convert all possible call-sites to the new abstracted
code at once. But I find that converting at least _one_ is a good litmus
test to confirm that a new interface is generally useful.

-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 2/3] format_config: simplify buffer handling

2015-08-21 Thread Jeff King
On Fri, Aug 21, 2015 at 10:43:58AM -0700, Junio C Hamano wrote:

> Junio C Hamano  writes:
> 
> > I wonder if we can do this instead
> >
> > if (!omit_values) {
> > -   if (show_keys)
> > +   if (show_keys && value_)
> > strbuf_addch(buf, key_delim);
> >
> > though.  That would eliminate the need for rolling back.
> 
> No we cannot.  "config --bool --get-regexp" could get a NULL value_
> and has to turn it to " true".
> 
> Sorry for the noise.

Right, I had the same thought and reached the same conclusion.

By the way, I do not think the rollback by itself is gross, it is just
that it has to reproduce the "show_keys" logic. That is, it _really_
wants to be:

  else {
  /* nothing to show; rollback delim */
  if (we_added_delim)
  strbuf_setlen(buf, buf->len - 1);
  }

and I use "show_keys" as a proxy for "did we add it". Which is
reproducing the logic that you quoted above, and if the two ever get out
of sync, it will be a bug. So you could write it as:

  int we_added_delim = 0;
  if (show_keys) {
strbuf_addch(buf, key_delim);
we_added_delim = 1;
  }

I didn't, because it's ugly, and the function is short enough and
unlikely enough to change that it probably won't matter.

You could perhaps also write it as:

  size_t baselen = buf->len;
  if (show_keys)
strbuf_addch(buf, key_delim);
  ...
  else {
/* rollback delim */
strbuf_setlen(buf, baselen);
  }

-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: [WIP/PATCH 3/3] submodule: helper to run foreach in parallel

2015-08-21 Thread Junio C Hamano
Stefan Beller  writes:

> +struct submodule_args {
> + const char *name;
> + const char *path;
> + const char *sha1;
> + const char *toplevel;
> + const char *prefix;
> + const char **cmd;
> + struct submodule_output *out;
> + sem_t *mutex;
> +};

I do not see what submodule_output looks like in the patch, but I
guess you are capturing _all_ output from a task and emitting
everything at the end, after the task is done?

I have to wonder if that is what people would expect and more
importantly if that is the most useful.  I am sympathetic to the
desire to avoid the output totally mixed up from different processes
emitting things in an uncoordinated manner, and "slurp everything
and then show everything in one go" is certainly _one_ way to do so,
but early feedback also counts.  Besides, because the order in which
tasks are dispatched and completed is unpredictable, you cannot
expect a machine parseable output _without_ assuming some help from
the command invoked by each task (e.g. by prefixing the task's output
with some string that identifies which submodule the output is about).

Once you assume that the command is _aware_ that it needs to help
the foreach-parallel infrastructure so that the user can sift their
collective outputs to make sense of them, wouldn't a line-buffered
intermixing also acceptable, and wouldn't it be a much lower impact
approach to solve the same problem?
--
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 2/3] run-commands: add an async queue processor

2015-08-21 Thread Junio C Hamano
Stefan Beller  writes:

> This adds functionality to do work in parallel.
>
> The whole life cycle of such a thread pool would look like
>
> struct task_queue * tq = create_task_queue(32); // no of threads
> for (...)
> add_task(tq, process_one_item_function, item); // non blocking
> ...
> int ret = finish_task_queue(tq); // blocks until all tasks are done
> if (!tq)
> die ("Not all items were be processed");
>
> The caller must take care of handling the output.
>
> Signed-off-by: Stefan Beller 
> ---
>
> I sent this a while ago to the list, no comments on it :(

The primary reason I suspect is because you sent to a wrong set of
people.  Submodule folks have largely been working in the scripted
ones, and may not necessarily be the ones who are most familiar with
the run-command infrastructure.

"shortlog --no-merges" tells me that the obvious suspects are j6t
and peff.

> The core functionality stayed the same, but I hope to improved naming and
> location of the code.
>
> The WIP is only for the NO_PTHREADS case.

>  run-command.c | 212 
> ++
>  run-command.h |  30 +
>  2 files changed, 230 insertions(+), 12 deletions(-)
>
> diff --git a/run-command.c b/run-command.c
> index 28e1d55..4029011 100644
> --- a/run-command.c
> +++ b/run-command.c
> @@ -4,6 +4,21 @@
>  #include "sigchain.h"
>  #include "argv-array.h"
>  
> +#ifdef NO_PTHREADS
> +
> +#else
> +
> +#include "thread-utils.h"
> +
> +#include 
> +#include 
> +#include 
> +#include 
> +
> +#endif
> +
> +#include "git-compat-util.h"
> +

This goes against the way we have been organizing the header files.

http://thread.gmane.org/gmane.comp.version-control.git/276241/focus=276265

> @@ -668,6 +683,22 @@ int git_atexit(void (*handler)(void))
>  
>  #endif
>  
> +void setup_main_thread()

void setup_main_thread(void)

> @@ -852,3 +872,171 @@ int capture_command(struct child_process *cmd, struct 
> strbuf *buf, size_t hint)
>   close(cmd->out);
>   return finish_command(cmd);
>  }
> +
> +#ifndef NO_PTHREADS
> +struct job_list {
> + int (*fct)(struct task_queue *aq, void *task);
> + void *task;
> + struct job_list *next;
> +};
> +#endif
> +
> +struct task_queue {
> +#ifndef NO_PTHREADS
> + /*
> +  * To avoid deadlocks always aquire the semaphores with lowest priority

acquire.

> +  * first, priorites are in descending order as listed.
> +  *
> +  * The `mutex` is a general purpose lock for modifying data in the async
> +  * queue, such as adding a new task or adding a return value from
> +  * an already run task.
> +  *
> +  * `workingcount` and `freecount` are opposing semaphores, the sum of
> +  * their values should equal `max_threads` at any time while the `mutex`
> +  * is available.
> +  */
> + sem_t mutex;
> + sem_t workingcount;
> + sem_t freecount;
> +
> + pthread_t *threads;
> + unsigned max_threads;
> +
> + struct job_list *first;
> + struct job_list *last;
> +#endif
> + int early_return;
> +};
> +
> +#ifndef NO_PTHREADS
> +
> +static void get_task(struct task_queue *aq,
> +  int (**fct)(struct task_queue *aq, void *task),
> +  void **task,
> +  int *early_return)
> +{
> + struct job_list *job;
> +
> + sem_wait(&aq->workingcount);
> + sem_wait(&aq->mutex);
> +
> + if (!aq->first)
> + die("BUG: internal error with dequeuing jobs for threads");
> + job = aq->first;
> + *fct = job->fct;
> + *task = job->task;
> + aq->early_return |= *early_return;
> + *early_return = aq->early_return;
> + aq->first = job->next;
> + if (!aq->first)
> + aq->last = NULL;
> +
> + sem_post(&aq->freecount);
> + sem_post(&aq->mutex);
> +
> + free(job);
> +}
> +
> +static void* dispatcher(void *args)

static void *dispatcher()

> +{
> + void *task;
> + int (*fct)(struct task_queue *aq, void *data);

s/data/task/?

> + int early_return = 0;
> + struct task_queue *aq = args;
> +
> + get_task(aq, &fct, &task, &early_return);
> + while (fct || early_return != 0) {
> + early_return = fct(aq, task);
> + get_task(aq, &fct, &task, &early_return);
> + }

If the func said "we are done, you may stop dispatching now", do you
still want to do another get_task()?

> + pthread_exit(0);
> +}
> +#endif
> +
> +struct task_queue *create_task_queue(unsigned max_threads)
> +{
> + struct task_queue *aq = xmalloc(sizeof(*aq));
> +
> +#ifndef NO_PTHREADS
> + int i;
> + if (!max_threads)
> + aq->max_threads = online_cpus();
> + else
> + aq->max_threads = max_threads;
> +
> + sem_init(&aq->mutex, 0, 1);
> + sem_init(&aq->workingcount, 0, 0);
> + sem_init(&aq->freecount, 0, aq->max_threads);
> + aq->threads = xmalloc(aq->max_threads * sizeof(pthread_t));
> +
> +   

[PATCH 4/3] builtin/log.c: minor reformat

2015-08-21 Thread Junio C Hamano
Two logical lines that were not overly long was split in the middle,
which made them read worse.

Signed-off-by: Junio C Hamano 
---
 builtin/log.c | 6 ++
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/builtin/log.c b/builtin/log.c
index 0cdd889..a491d3d 100644
--- a/builtin/log.c
+++ b/builtin/log.c
@@ -342,8 +342,7 @@ static int cmd_log_walk(struct rev_info *rev)
 * retain that state information if replacing rev->diffopt in this loop
 */
while ((commit = get_revision(rev)) != NULL) {
-   if (!log_tree_commit(rev, commit) &&
-   rev->max_count >= 0)
+   if (!log_tree_commit(rev, commit) && rev->max_count >= 0)
/*
 * We decremented max_count in get_revision,
 * but we didn't actually show the commit.
@@ -1464,8 +1463,7 @@ int cmd_format_patch(int argc, const char **argv, const 
char *prefix)
continue;
}
 
-   if (ignore_if_in_upstream &&
-   has_commit_patch_id(commit, &ids))
+   if (ignore_if_in_upstream && has_commit_patch_id(commit, &ids))
continue;
 
nr++;
--
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 v4] git-p4: fix faulty paths for case insensitive systems

2015-08-21 Thread Junio C Hamano
larsxschnei...@gmail.com writes:

> From: Lars Schneider 
>
> PROBLEM:
> We run P4 servers on Linux and P4 clients on Windows. For an unknown
> reason the file path for a number of files in P4 does not match the
> directory path with respect to case sensitivity.
>
> E.g. `p4 files` might return
> //depot/path/to/file1
> //depot/PATH/to/file2
>
> If you use P4/P4V then these files end up in the same directory, e.g.
> //depot/path/to/file1
> //depot/path/to/file2
>
> If you use git-p4 then all files not matching the correct file path
> (e.g. `file2`) will be ignored.
>
> SOLUTION:
> Identify path names that are different with respect to case sensitivity.
> If there are any then run `p4 dirs` to build up a dictionary
> containing the "correct" cases for each path. It looks like P4
> interprets "correct" here as the existing path of the first file in a
> directory. The path dictionary is used later on to fix all paths.
>
> This is only applied if the parameter "--ignore-path-case" is passed to
> the git-p4 clone command.
>
>
> Signed-off-by: Lars Schneider 
> ---

Thanks.  A few comments.

 - Have you checked "git log" on our history and notice how nobody
   says "PROBLEM:" and "SOLUTION:" in capital letters?  Don't try to
   be original in the form; your contributions are already original
   and valuable in the substance ;-)

 - I think I saw v3 yesterday.  It would be nice to see a brief
   description of what has been updated in this version.

I do not do Perforce and am not familiar enough with this code to
judge myself.  Will wait for area experts (you have them CC'ed, which
is good) to comment.

> diff --git a/git-p4.py b/git-p4.py
> index 073f87b..61a587b 100755
> --- a/git-p4.py
> +++ b/git-p4.py
> @@ -1931,7 +1931,7 @@ class View(object):
>  (self.client_prefix, clientFile))
>  return clientFile[len(self.client_prefix):]
>  
> -def update_client_spec_path_cache(self, files):
> +def update_client_spec_path_cache(self, files, fixPathCase = None):

I didn't check the remainder of the file, but I thought it is
customery *not* to have spaces around '=' when the parameter is
written with its default value in Python?

> diff --git a/t/t9821-git-p4-path-variations.sh 
> b/t/t9821-git-p4-path-variations.sh
> ...
> +test_expect_success 'Clone the repo and WITHOUT path fixing' '
> + client_view "//depot/One/... //client/..." &&
> + git p4 clone --use-client-spec --destination="$git" //depot &&
> + test_when_finished cleanup_git &&
> + (
> + cd "$git" &&
> + # This method is used instead of "test -f" to ensure the case is
> + # checked even if the test is executed on case-insensitive file 
> systems.
> + cat >expect <<-\EOF &&
> + two/File2.txt
> + EOF

I think we usually write the body of the indented here text
(i.e. "<<-") indented to the same level as the command and
delimiter, i.e.

cat >expect <<-\EOF &&
body of the here document line 1
body of the here document line 2
...
EOF

> + git ls-files >actual &&
> + test_cmp expect actual
> + )
> +'

I think you used to check the result with "find .", i.e. what the
filesystem actually recorded.  "ls-files" gives what the index
records (i.e. to be committed if you were to make a new commit from
that index).  They can be different in case on case-insensitive
filesystems, which I think are the ones that are most problematic
with the issue your patch is trying to address.

You are verifying what the set of "canonical" paths should be by
checking ls-files output.  I think that is what you intended to do
(i.e. I am saying "I think the code is more correct than the earlier
round that used find"), but I just am double checking.

> +test_expect_success 'Add a new file and clone the repo WITH path fixing' '
> + client_view "//depot/... //client/..." &&
> + (
> + cd "$cli" &&
> +
> + mkdir -p One/two &&

A blank after 'cd' only in this one but not others.  A blank line is
a good vehicle to convey that blocks of text above and below it are
logically separate, but use it consistently.  I _think_ this blank
line can go.

> + >One/two/File0.txt &&
> + p4 add One/two/File0.txt &&

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 2/3] format_config: simplify buffer handling

2015-08-21 Thread Junio C Hamano
Junio C Hamano  writes:

> I wonder if we can do this instead
>
>   if (!omit_values) {
> - if (show_keys)
> + if (show_keys && value_)
>   strbuf_addch(buf, key_delim);
>
> though.  That would eliminate the need for rolling back.

No we cannot.  "config --bool --get-regexp" could get a NULL value_
and has to turn it to " true".

Sorry for the noise.
--
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/3] format_config: simplify buffer handling

2015-08-21 Thread Junio C Hamano
Jeff King  writes:

> When formatting a config value into a strbuf, we may end
> up stringifying it into a fixed-size buffer using sprintf,
> and then copying that buffer into the strbuf. We can
> eliminate the middle-man (and drop some calls to sprintf!)
> by writing directly to the strbuf.
>
> The reason it was written this way in the first place is
> that we need to know before writing the value whether to
> insert a delimiter. Instead of delaying the write of the
> value, we speculatively write the delimiter, and roll it
> back in the single case that cares.
>
> Signed-off-by: Jeff King 
> ---
> I admit the rollback is a little gross. The other option would be adding
> the delimiter in each of the conditional branches, which is also kind of
> nasty.

I actually am fine with this rollback.  The "variable alone stands
for true" is not something a user can produce from the command line
very easily, so having to rollback is a rare event anyway.

I wonder if we can do this instead

if (!omit_values) {
-   if (show_keys)
+   if (show_keys && value_)
strbuf_addch(buf, key_delim);

though.  That would eliminate the need for rolling back.

I briefly wondered how such a change would interact with

if (types == TYPE_INT)
strbuf_addf(buf, "%"PRId64,
git_config_int64(key_, value_ ? value_ : ""));

that immediately follows it, but this "turn NULL into an empty
string" may be bogus in the first place, in the sense that
git_config_int64() should complain about a NULL value_ the same way
as it would complain about an empty string---both them are not an
integer.  And indeed:

 - git_parse_int64() that is called from git_config_int64() is
   prepared to take both "" and NULL and return failure with EINVAL;

 - die_bad_number() that is eventually called when parsing fails by
   git_config_int64() is prepared to take NULL and turns it to an
   empty string.

So perhaps we could do this squashed in?

 builtin/config.c | 9 -
 1 file changed, 4 insertions(+), 5 deletions(-)

diff --git a/builtin/config.c b/builtin/config.c
index 71acc44..593b1ae 100644
--- a/builtin/config.c
+++ b/builtin/config.c
@@ -111,12 +111,12 @@ static int format_config(struct strbuf *buf, const char 
*key_, const char *value
if (show_keys)
strbuf_addstr(buf, key_);
if (!omit_values) {
-   if (show_keys)
+   if (show_keys && value_)
strbuf_addch(buf, key_delim);
 
if (types == TYPE_INT)
strbuf_addf(buf, "%"PRId64,
-   git_config_int64(key_, value_ ? value_ : 
""));
+   git_config_int64(key_, value_));
else if (types == TYPE_BOOL)
strbuf_addstr(buf, git_config_bool(key_, value_) ?
  "true" : "false");
@@ -136,9 +136,8 @@ static int format_config(struct strbuf *buf, const char 
*key_, const char *value
} else if (value_) {
strbuf_addstr(buf, value_);
} else {
-   /* Just show the key name; back out delimiter */
-   if (show_keys)
-   strbuf_setlen(buf, buf->len - 1);
+   /* Just show the key name */
+   ;
}
}
strbuf_addch(buf, term);


--
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] contrib: teach completion about git-worktree options and arguments

2015-08-21 Thread Junio C Hamano
Eric Sunshine  writes:

> On Thu, Jul 23, 2015 at 4:49 PM, Eric Sunshine  
> wrote:
>> Complete subcommands 'add' and 'prune', as well as their respective
>> options --force, --detach, --dry-run, --verbose, and --expire. Also
>> complete 'refname' in "git worktree add [-b ] 
>> ".
>
> Ping[1]?
>
> [1]: http://article.gmane.org/gmane.comp.version-control.git/274526

Ping indeed?

>
>> Signed-off-by: Eric Sunshine 
>> ---
>>
>> This is RFC since this is my first foray into the Git completion script,
>> and there are likely better and more idiomatic ways to accomplish this.
>>
>>  contrib/completion/git-completion.bash | 32 
>>  1 file changed, 32 insertions(+)
>>
>> diff --git a/contrib/completion/git-completion.bash 
>> b/contrib/completion/git-completion.bash
>> index c97c648..07c34ef 100644
>> --- a/contrib/completion/git-completion.bash
>> +++ b/contrib/completion/git-completion.bash
>> @@ -2564,6 +2564,38 @@ _git_whatchanged ()
>> _git_log
>>  }
>>
>> +_git_worktree ()
>> +{
>> +   local subcommands='add prune'
>> +   local subcommand="$(__git_find_on_cmdline "$subcommands")"
>> +   local c=2 n=0 refpos=2
>> +   if [ -z "$subcommand" ]; then
>> +   __gitcomp "$subcommands"
>> +   else
>> +   case "$subcommand,$cur" in
>> +   add,--*)
>> +   __gitcomp "--force --detach"
>> +   ;;
>> +   add,*)
>> +   while [ $c -lt $cword ]; do
>> +   case "${words[c]}" in
>> +   --*) ;;
>> +   -[bB]) ((refpos++)) ;;
>> +   *) ((n++)) ;;
>> +   esac
>> +   ((c++))
>> +   done
>> +   if [ $n -eq $refpos ]; then
>> +   __gitcomp_nl "$(__git_refs)"
>> +   fi
>> +   ;;
>> +   prune,--*)
>> +   __gitcomp "--dry-run --verbose --expire"
>> +   ;;
>> +   esac
>> +   fi
>> +}
>> +
>>  __git_main ()
>>  {
>> local i c=1 command __git_dir
>> --
>> 2.5.0.rc3.407.g68aafd0
--
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 v4] git-p4: fix faulty paths for case insensitive systems

2015-08-21 Thread larsxschneider
From: Lars Schneider 

PROBLEM:
We run P4 servers on Linux and P4 clients on Windows. For an unknown
reason the file path for a number of files in P4 does not match the
directory path with respect to case sensitivity.

E.g. `p4 files` might return
//depot/path/to/file1
//depot/PATH/to/file2

If you use P4/P4V then these files end up in the same directory, e.g.
//depot/path/to/file1
//depot/path/to/file2

If you use git-p4 then all files not matching the correct file path
(e.g. `file2`) will be ignored.

SOLUTION:
Identify path names that are different with respect to case sensitivity.
If there are any then run `p4 dirs` to build up a dictionary
containing the "correct" cases for each path. It looks like P4
interprets "correct" here as the existing path of the first file in a
directory. The path dictionary is used later on to fix all paths.

This is only applied if the parameter "--ignore-path-case" is passed to
the git-p4 clone command.

Signed-off-by: Lars Schneider 
---
 git-p4.py |  82 ++--
 t/t9821-git-p4-path-variations.sh | 109 ++
 2 files changed, 187 insertions(+), 4 deletions(-)
 create mode 100755 t/t9821-git-p4-path-variations.sh

diff --git a/git-p4.py b/git-p4.py
index 073f87b..61a587b 100755
--- a/git-p4.py
+++ b/git-p4.py
@@ -1931,7 +1931,7 @@ class View(object):
 (self.client_prefix, clientFile))
 return clientFile[len(self.client_prefix):]
 
-def update_client_spec_path_cache(self, files):
+def update_client_spec_path_cache(self, files, fixPathCase = None):
 """ Caching file paths by "p4 where" batch query """
 
 # List depot file paths exclude that already cached
@@ -1950,6 +1950,8 @@ class View(object):
 if "unmap" in res:
 # it will list all of them, but only one not unmap-ped
 continue
+if fixPathCase:
+res['depotFile'] = fixPathCase(res['depotFile'])
 self.client_spec_path_cache[res['depotFile']] = 
self.convert_client_path(res["clientFile"])
 
 # not found files or unmap files set to ""
@@ -1987,6 +1989,7 @@ class P4Sync(Command, P4UserMap):
  help="Maximum number of changes to 
import"),
 optparse.make_option("--changes-block-size", 
dest="changes_block_size", type="int",
  help="Internal block size to use when 
iteratively calling p4 changes"),
+optparse.make_option("--ignore-path-case", 
dest="ignorePathCase", action="store_true"),
 optparse.make_option("--keep-path", dest="keepRepoPath", 
action='store_true',
  help="Keep entire BRANCH/DIR/SUBDIR 
prefix during import"),
 optparse.make_option("--use-client-spec", 
dest="useClientSpec", action='store_true',
@@ -2017,6 +2020,7 @@ class P4Sync(Command, P4UserMap):
 self.maxChanges = ""
 self.changes_block_size = None
 self.keepRepoPath = False
+self.ignorePathCase = False
 self.depotPaths = None
 self.p4BranchesInGit = []
 self.cloneExclude = []
@@ -2049,7 +2053,8 @@ class P4Sync(Command, P4UserMap):
 files = []
 fnum = 0
 while commit.has_key("depotFile%s" % fnum):
-path =  commit["depotFile%s" % fnum]
+path = commit["depotFile%s" % fnum]
+path = self.fixPathCase(path)
 
 if [p for p in self.cloneExclude
 if p4PathStartsWith(path, p)]:
@@ -2113,7 +2118,9 @@ class P4Sync(Command, P4UserMap):
 branches = {}
 fnum = 0
 while commit.has_key("depotFile%s" % fnum):
-path =  commit["depotFile%s" % fnum]
+path = commit["depotFile%s" % fnum]
+path = self.fixPathCase(path)
+
 found = [p for p in self.depotPaths
  if p4PathStartsWith(path, p)]
 if not found:
@@ -2240,6 +2247,10 @@ class P4Sync(Command, P4UserMap):
 if marshalled["code"] == "error":
 if "data" in marshalled:
 err = marshalled["data"].rstrip()
+
+if "depotFile" in marshalled:
+marshalled['depotFile'] = self.fixPathCase(marshalled['depotFile'])
+
 if err:
 f = None
 if self.stream_have_file_info:
@@ -2314,6 +2325,7 @@ class P4Sync(Command, P4UserMap):
 
 # do the last chunk
 if self.stream_file.has_key('depotFile'):
+self.stream_file['depotFile'] = 
self.fixPathCase(self.stream_file['depotFile'])
 self.streamOneP4File(self.stream_file, self.stream_contents)
 
 def make_email(self, userid):
@@ -2371,7 +2383,8 @@ class P4Sync(Command, P4UserMap):
 sys.stderr.write("Ignoring file outside of prefix: %s\n" % 
f['path'])
 
 if self.clientSpecDirs:
-self.clientS

Re: [PATCH] Documentation/config: fix inconsistent label

2015-08-21 Thread Junio C Hamano
Andreas Schwab  writes:

> Change  to  in the description of
> gc.*.reflogExpireUnreachable, since that is what the text refers to.
>
> Signed-off-by: Andreas Schwab 
> ---

Makes sense.  Thanks.

>  Documentation/config.txt | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/Documentation/config.txt b/Documentation/config.txt
> index 75ec02e..b4f7c46 100644
> --- a/Documentation/config.txt
> +++ b/Documentation/config.txt
> @@ -1329,7 +1329,7 @@ gc..reflogExpire::
>   the refs that match the .
>  
>  gc.reflogExpireUnreachable::
> -gc..reflogExpireUnreachable::
> +gc..reflogExpireUnreachable::
>   'git reflog expire' removes reflog entries older than
>   this time and are not reachable from the current tip;
>   defaults to 30 days. The value "now" expires all entries
> -- 
> 2.5.0
--
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/PATCH] t9350-fast-export: Add failing test for symlink-to-directory

2015-08-21 Thread Anders Kaseorg
On Fri, 21 Aug 2015, Jeff King wrote:
>   - we may still have the opposite problem with renames. That is, a
> rename is _also_ a deletion, but will go to the end. So I would
> expect renaming the symlink "foo" to "bar" and then adding
> "foo/world" would end up with:
> 
>M 100644 :3 foo/world
>R foo bar
> 
> (because we push renames to the end in our sort). And indeed,
> importing that does seem to get it wrong (we end up with "bar/world"
> and no symlink).
> 
> We can't fix the ordering in the second case without breaking the first
> case. So I'm not sure it's fixable on the fast-export end.

Hmm, renames have a more fundamental ordering problem: swapping two 
(normal) files and using fast-export -C -B results in

  R foo bar
  R bar foo

which cannot be reimported correctly without fast-import fixes.

Anders
--
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] am: rename "struct tree_desc t" to "desc" for readability

2015-08-21 Thread Junio C Hamano
David Aguilar  writes:

> Signed-off-by: David Aguilar 
> ---
>  builtin/am.c | 8 
>  1 file changed, 4 insertions(+), 4 deletions(-)

Naming the tree_desc parameter given to unpack_trees() as "t" is
(unfortunately) an established convention, just like we often use
"i" and "j" in for() loop control.

Descriptive names are nicer, especially on the calling sites, but we
have quite a many hits from

$ git grep unpack_trees\( \*.c

so perhaps do this as a clean-up patch after dust settles for all
the existing callers in archive, clone, commit, merge, read-tree,
reset, diff-lib, and merge-recursive?
--
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/3] am: do not corrupt the index stat state

2015-08-21 Thread Junio C Hamano
David Aguilar  writes:

> Reported-by: Linus Torvalds
> Signed-off-by: David Aguilar 
> @@ -1975,10 +1977,20 @@ static int clean_index(const unsigned char *head, 
> const unsigned char *remote)
>  
>   memset(&pathspec, 0, sizeof(pathspec));
>  
> + memset(&opts, 0, sizeof(opts));
> + opts.fn = oneway_merge;
> + opts.pathspec = &pathspec;
> + opts.src_index = &the_index;
> + opts.dst_index = &the_index;
> + opts.head_idx = 1;
> + opts.merge = 1;
> + opts.reset = 1;
> + init_tree_desc(&desc, remote_tree->buffer, remote_tree->size);
> +
>   lock_file = xcalloc(1, sizeof(struct lock_file));
>   hold_locked_index(lock_file, 1);
>  
> - if (read_tree(remote_tree, 0, &pathspec)) {
> + if (unpack_trees(1, &desc, &opts)) {

I think the same fix was done in 3ecc7040 (am --skip/--abort: merge
HEAD/ORIG_HEAD tree into index, 2015-08-19).
--
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] describe --contains: default to HEAD when no commit-ish is given

2015-08-21 Thread Junio C Hamano
SZEDER Gábor  writes:

> 'git describe --contains' doesn't default to HEAD when no commit is
> given, and it doesn't produce any output, not even an error:
>
>   ~/src/git ((v2.5.0))$ ./git describe --contains
>   ~/src/git ((v2.5.0))$ ./git describe --contains HEAD
>   v2.5.0^0

Good spotting. I think defaulting to HEAD is a good move.

> diff --git a/builtin/describe.c b/builtin/describe.c
> index ce36032b1f..0e31ac5cb9 100644
> --- a/builtin/describe.c
> +++ b/builtin/describe.c
> @@ -443,10 +443,13 @@ int cmd_describe(int argc, const char **argv, const 
> char *prefix)
>   if (pattern)
>   argv_array_pushf(&args, "--refs=refs/tags/%s", 
> pattern);
>   }
> - while (*argv) {
> - argv_array_push(&args, *argv);
> - argv++;
> - }
> + if (argc)

"What would this code do to 'describe --all --contains'?" was my
knee-jerk reaction, but the options are all parsed by this code and
nothing is delegated to name-rev, so 'if (!argc)' here is truly the
lack of any revisions to be described, which is good.

> + while (*argv) {
> + argv_array_push(&args, *argv);
> + argv++;
> + }
> + else
> + argv_array_push(&args, "HEAD");

By the way, I usually prefer a fatter 'else' clause when everything
else is equal, i.e.

if (!argc)
argv_array_push(&args, "HEAD"); /* default to HEAD */
else {
while (*argv) {
...
}
}

because it is easy to miss tiny else-clause while reading code, but
it is harder to miss tiny then-clause.  In this case, however, the
while loop can be replaced with argv_array_pushv() these days, so
perhaps

if (!argc)
argv_array_push(&args, "HEAD"); /* default to HEAD ... */
else
argv_array_pushv(&args, argv); /* or relay what we got */

or something?

>   return cmd_name_rev(args.argc, args.argv, prefix);
>   }

>  
> diff --git a/t/t6120-describe.sh b/t/t6120-describe.sh
> index 57d50156bb..bf52a0a1cc 100755
> --- a/t/t6120-describe.sh
> +++ b/t/t6120-describe.sh
> @@ -115,6 +115,14 @@ check_describe e-3-* --first-parent --tags
>  
>  check_describe $(git rev-parse --short HEAD) --exact-match --always HEAD
>  
> +test_expect_success 'describe --contains defaults to HEAD without 
> commit-ish' '
> + echo "A^0" >expect &&
> + git checkout A &&
> + test_when_finished "git checkout -" &&
> + git describe --contains >actual &&
> + test_cmp expect actual
> +'
>  : >err.expect
>  check_describe A --all A^0
>  test_expect_success 'no warning was displayed for A' '
--
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: Minor bug with help.autocorrect.

2015-08-21 Thread Jeff King
On Fri, Aug 21, 2015 at 09:10:35AM -0700, Junio C Hamano wrote:

> > $ git \#fetch
> > error: invalid key: pager.#fetch
> > error: invalid key: alias.#fetch
> > git: '#fetch' is not a git command. See 'git --help'.
> >
> > Did you mean this?
> > fetch
> 
> Thanks.  I somehow thought that we had some discussion on this
> earlier, perhaps
> 
>   http://thread.gmane.org/gmane.comp.version-control.git/263416/focus=263438
> 
> Peff, do you remember what (if anything) we decided to do about
> this?  I unfortunately don't X-<.

I think the plan is:

  1. squelch the warning message from the config code; even if we change
 the config format to pager.*.command, we will have to support
 pager.* for historical reasons.

  2. introduce pager.*.command so that "git foo_bar" can use
 pager.foo_bar.command.

We should do (1) in the near-term. We do not have to do (2) at all (and
people with funny command names are simply out of luck), but it would be
nice in the long run.

The patch from Tanay in $gmane/263888 accomplishes (1), but there was a
minor cleanup needed (checking the individual bit in "flags", rather
than the whole variable). Here it is with that fix:

-- >8 --
From: Tanay Abhra 
Subject: [PATCH] add a flag to supress errors in git_config_parse_key()

`git_config_parse_key()` is used to sanitize the input key.
Some callers of the function like `git_config_set_multivar_in_file()`
get the pre-sanitized key directly from the user so it becomes
necessary to raise an error specifying what went wrong when the entered
key is syntactically malformed.

Other callers like `configset_find_element()` get their keys from git
itself so a return value signifying error would be enough.  The error
output shown to the user is useless and confusing in this case, so add a
flag to suppress errors in such cases.

Helped-by: Junio C Hamano 
Helped-by: Jeff King 
Signed-off-by: Tanay Abhra 
Signed-off-by: Jeff King 
---
 builtin/config.c |  2 +-
 cache.h  |  4 +++-
 config.c | 21 ++---
 t/t7006-pager.sh |  9 +
 4 files changed, 27 insertions(+), 9 deletions(-)

diff --git a/builtin/config.c b/builtin/config.c
index 7188405..f6cfb10 100644
--- a/builtin/config.c
+++ b/builtin/config.c
@@ -200,7 +200,7 @@ static int get_value(const char *key_, const char *regex_)
goto free_strings;
}
} else {
-   if (git_config_parse_key(key_, &key, NULL)) {
+   if (git_config_parse_key(key_, &key, NULL, 0)) {
ret = CONFIG_INVALID_KEY;
goto free_strings;
}
diff --git a/cache.h b/cache.h
index 4e25271..4b95d7e 100644
--- a/cache.h
+++ b/cache.h
@@ -1410,6 +1410,8 @@ extern int update_server_info(int);
 
 #define CONFIG_REGEX_NONE ((void *)1)
 
+#define CONFIG_ERROR_QUIET 0x0001
+
 struct git_config_source {
unsigned int use_stdin:1;
const char *file;
@@ -1439,7 +1441,7 @@ extern int git_config_string(const char **, const char *, 
const char *);
 extern int git_config_pathname(const char **, const char *, const char *);
 extern int git_config_set_in_file(const char *, const char *, const char *);
 extern int git_config_set(const char *, const char *);
-extern int git_config_parse_key(const char *, char **, int *);
+extern int git_config_parse_key(const char *, char **, int *, unsigned int);
 extern int git_config_set_multivar(const char *, const char *, const char *, 
int);
 extern int git_config_set_multivar_in_file(const char *, const char *, const 
char *, const char *, int);
 extern int git_config_rename_section(const char *, const char *);
diff --git a/config.c b/config.c
index 9fd275f..dd0cb52 100644
--- a/config.c
+++ b/config.c
@@ -1314,7 +1314,7 @@ static struct config_set_element 
*configset_find_element(struct config_set *cs,
 * `key` may come from the user, so normalize it before using it
 * for querying entries from the hashmap.
 */
-   ret = git_config_parse_key(key, &normalized_key, NULL);
+   ret = git_config_parse_key(key, &normalized_key, NULL, 
CONFIG_ERROR_QUIET);
 
if (ret)
return NULL;
@@ -1847,11 +1847,14 @@ int git_config_set(const char *key, const char *value)
  * lowercase section and variable name
  * baselen - pointer to int which will hold the length of the
  *   section + subsection part, can be NULL
+ * flags - we respect CONFIG_ERROR_QUIET to toggle whether the function raises
+ * an error on a syntactically malformed key
  */
-int git_config_parse_key(const char *key, char **store_key, int *baselen_)
+int git_config_parse_key(const char *key, char **store_key, int *baselen_, 
unsigned int flags)
 {
int i, dot, baselen;
const char *last_dot = strrchr(key, '.');
+   int quiet = flags & CONFIG_ERROR_QUIET;
 
/*
 * Since "key" actually contains the section name and the real
@@ -1859,12 +1862,14 @@ in

Re: Minor bug with help.autocorrect.

2015-08-21 Thread Junio C Hamano
Bjørnar Snoksrud  writes:

> If you mis-type a git command starting with a non-letter, git
> internals will spit out some errors at you.
>
> $ git 5fetch
> error: invalid key: pager.5fetch
> error: invalid key: alias.5fetch
> git: '5fetch' is not a git command. See 'git --help'.
>
> Did you mean this?
> fetch
>
> $ git \#fetch
> error: invalid key: pager.#fetch
> error: invalid key: alias.#fetch
> git: '#fetch' is not a git command. See 'git --help'.
>
> Did you mean this?
> fetch

Thanks.  I somehow thought that we had some discussion on this
earlier, perhaps

  http://thread.gmane.org/gmane.comp.version-control.git/263416/focus=263438

Peff, do you remember what (if anything) we decided to do about
this?  I unfortunately don't X-<.

--
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] describe: make '--always' fallback work after '--exact-match' failed

2015-08-21 Thread Junio C Hamano
SZEDER Gábor  writes:

> Quoting Junio C Hamano :
>
>> Well, that can be argued both ways.
> ...
>
> 'git describe' errors out by default if it can't describe the given
> commit.

Yes.  "describe" always fails when it cannot produce an acceptable
description.

And "--always" and "--exact-match" are two incompatible ways for
users to change what is considered an acceptable description.

 - With "--exact-match" and "--always", the definition of
   "acceptable" changes: by default, only a name based on some
   anchor point is acceptable.

   - "--always" loosens the definition and also allows an
 abbreviated commit object name as acceptable.

   - "--exact-match" tightens the definition.  In addition to "only
 a name based on some anchor point is acceptable", it requires
 that "based on" to be "0 distance from the anchor point".  The
 help text says succinctly: "*ONLY* output exact matches".

If you allow a request with "--exact-match" to show something that
is not an exact match, that no longer is "--exact-match".  Allowing
to mix "--always" to that option breaks it, as what the command does
no longer is to "only outputs exact matches".

 - One option "--exact-match" says that it is wrong to show anything
   but exact matches.

 - The other option "--always" says it is willing to show a name
   that is not an exact match.  

These are competing goals.  You give preference to the latter, but
that is not the only valid point of view.

And that is why I said it can be argued both ways.  I think these
two are fundamentally incompatible.


[Footnote]

*1* Other parts of "'describe' only considers a name based on some
anchor point as acceptable." are also modified by various
options:

- With "--contains", the definition of "based on" changes
  direction: a commit may be described as somewhere ahead of an
  anchor point by default, but can be described as somewhere behind
  of an anchor point.

- With "--all" and "--tags", the definition of "anchor point"
  changes: by default, only annotated tags are possible anchor
  points.

--
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] Documentation/config: fix inconsistent label

2015-08-21 Thread Andreas Schwab
Change  to  in the description of
gc.*.reflogExpireUnreachable, since that is what the text refers to.

Signed-off-by: Andreas Schwab 
---
 Documentation/config.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Documentation/config.txt b/Documentation/config.txt
index 75ec02e..b4f7c46 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -1329,7 +1329,7 @@ gc..reflogExpire::
the refs that match the .
 
 gc.reflogExpireUnreachable::
-gc..reflogExpireUnreachable::
+gc..reflogExpireUnreachable::
'git reflog expire' removes reflog entries older than
this time and are not reachable from the current tip;
defaults to 30 days. The value "now" expires all entries
-- 
2.5.0

-- 
Andreas Schwab, sch...@linux-m68k.org
GPG Key fingerprint = 58CA 54C7 6D53 942B 1756  01D3 44D5 214B 8276 4ED5
"And now for something completely different."
--
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 7/9] builtin/send-pack.c: Use option parsing API

2015-08-21 Thread Jeff King
On Wed, Aug 19, 2015 at 03:46:25PM -0400, Dave Borowitz wrote:

> >> +   unsigned dry_run = 0;
> >> +   unsigned send_mirror = 0;
> >> +   unsigned force_update = 0;
> >> +   unsigned quiet = 0;
> >> +   unsigned push_cert = 0;
> >> +   unsigned use_thin_pack = 0;
> >> +   unsigned atomic = 0;
> >> +   unsigned stateless_rpc = 0;
> >
> > First I thought:
> > You could write to the args flags directly from the options. No
> > need to have (most of)
> > the variables around here and copy over the values. You'd need to
> > use OPT_BIT instead
> > for setting a specific bit though
> > but then I realized we do not have a direct bit field in args, which
> > would make it a bit unreadable.
> 
> Right, and &args->push_cert etc. is invalid, and I didn't know if it
> was ok to expand the args struct to be several words longer. But I'm
> not a C programmer so I'm happy to take suggestions how to make this
> more idiomatic.

I think it would be fine to expand it. The reason to use bitfields is to
save memory, and there is literally only one of these structs per
program. I'm sure we can afford the extra dozen bytes.

Making the struct members single-bits also communicates to readers that
they are true booleans, but I think a comment in the declaration of
send_pack_args could do the same.

-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: [BUG/PATCH] t9350-fast-export: Add failing test for symlink-to-directory

2015-08-21 Thread Jeff King
On Wed, Aug 19, 2015 at 03:46:27PM -0400, Anders Kaseorg wrote:

> git fast-export | git fast-import fails to preserve a commit that replaces 
> a symlink with a directory.  Add a failing test case demonstrating this 
> bug.
> 
> The fast-export output for the commit in question looks like
> 
>   commit refs/heads/master
>   mark :4
>   author …
>   committer …
>   data 4
>   two
>   M 100644 :1 foo/world
>   D foo
> 
> fast-import deletes the symlink foo and ignores foo/world.  Swapping the M 
> line with the D line would give the correct result.

Thanks for providing a patch to the tests. That is my favorite form of
bug report. :)

The problem seems to be that we output the entries in a "depth first"
way; "foo/bar" always comes before "foo", to cover the cases explained
in 060df62 (fast-export: Fix output order of D/F changes, 2010-07-09).

I'm tempted to say we would want to do all deletions (at any level)
first, to make room for new files. That patch looks like:

diff --git a/builtin/fast-export.c b/builtin/fast-export.c
index d23f3be..336fd6f 100644
--- a/builtin/fast-export.c
+++ b/builtin/fast-export.c
@@ -267,6 +267,14 @@ static int depth_first(const void *a_, const void *b_)
const char *name_a, *name_b;
int len_a, len_b, len;
int cmp;
+   int deletion;
+
+   /*
+* Move all deletions first, to make room for any later modifications.
+*/
+   deletion = (b->status == 'D') - (a->status == 'D');
+   if (deletion)
+   return deletion;
 
name_a = a->one ? a->one->path : a->two->path;
name_b = b->one ? b->one->path : b->two->path;


and does indeed pass your test. But I'm not sure that covers all cases,
and I'm not sure it doesn't make some cases worse:

  - if we moved a deletion to the front, is it possible for that path to
have been the source side of a copy or rename, that is now broken? I
don't _think_ so. If it's a copy, then the file by definition cannot
also be deleted (that would make it a rename, not a copy). We could
have a copy along with a rename, but again, then we don't have a
delete (we have a rename, which is explicitly bumped to the end for
this reason).

  - we may still have the opposite problem with renames. That is, a
rename is _also_ a deletion, but will go to the end. So I would
expect renaming the symlink "foo" to "bar" and then adding
"foo/world" would end up with:

   M 100644 :3 foo/world
   R foo bar

(because we push renames to the end in our sort). And indeed,
importing that does seem to get it wrong (we end up with "bar/world"
and no symlink).

We can't fix the ordering in the second case without breaking the first
case. So I'm not sure it's fixable on the fast-export end.

-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


git log date filter behavior with --date-order

2015-08-21 Thread Kirill Likhodedov
Hi,

I’ve faced a strange behavior when filtering git log by date.

When used with “--date-order” it gives significantly less results that when 
used without that option:

#  git log --pretty=oneline --remotes "--after=Wed May 20 23:00:00 MSK 2015" 
"--before=Fri May 22 00:00:00 MSK 2015" -- | wc -l
  85
#  git log --pretty=oneline --remotes "--after=Wed May 20 23:00:00 MSK 2015" 
"--before=Fri May 22 00:00:00 MSK 2015" --date-order -- | wc -l
  25

My assumption is that git log walks from the specified heads down to the past 
until it finds a commit which commit date matches the filter. Then it continues 
until it finds a commit which commit date doesn’t match the filter. Is it true?

Commits from “matching” and “unmatching” parts of the output are located in 
different branches which are being developed in parallel. 
AFAIU the flag “--date-order” is meant to place commits from different branches 
near each other, if they were performed at the same time.

But when I looked both at the “matching" and the “unmatching” commits in the 
whole `git log --date-order` view, I’ve noticed that they are placed really far 
away from each other (with about 4K commits between them).

Could you please give me a hint, why can git log --date-order behave like that? 

I’ll be happy to provide more details if needed. 

Thanks a lot!
Kirill.--
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] describe --contains: default to HEAD when no commit-ish is given

2015-08-21 Thread SZEDER Gábor
'git describe --contains' doesn't default to HEAD when no commit is
given, and it doesn't produce any output, not even an error:

  ~/src/git ((v2.5.0))$ ./git describe --contains
  ~/src/git ((v2.5.0))$ ./git describe --contains HEAD
  v2.5.0^0

Unlike other 'git describe' options, the '--contains' code path is
implemented by calling 'name-rev' with a bunch of options plus all the
commit-ishes that were passed to 'git describe'.  If no commit-ish was
present, then 'name-rev' got invoked with none, which then leads to the
behavior illustrated above.

Porcelain commands usually default to HEAD when no commit-ish is given,
and 'git describe' already does so in all other cases, so it should do
so with '--contains' as well.

Pass HEAD to 'name-rev' when no commit-ish is given on the command line
to make '--contains' behave consistently with other 'git describe'
options.

'git describe's short help already indicates that the commit-ish is
optional, but the synopsis in the man page doesn't, so update it
accordingly as well.

Signed-off-by: SZEDER Gábor 
---
 Documentation/git-describe.txt |  4 ++--
 builtin/describe.c | 11 +++
 t/t6120-describe.sh|  8 
 3 files changed, 17 insertions(+), 6 deletions(-)

diff --git a/Documentation/git-describe.txt b/Documentation/git-describe.txt
index e045fc73f8..c8f28c8c86 100644
--- a/Documentation/git-describe.txt
+++ b/Documentation/git-describe.txt
@@ -9,7 +9,7 @@ git-describe - Describe a commit using the most recent tag 
reachable from it
 SYNOPSIS
 
 [verse]
-'git describe' [--all] [--tags] [--contains] [--abbrev=] ...
+'git describe' [--all] [--tags] [--contains] [--abbrev=] [...]
 'git describe' [--all] [--tags] [--contains] [--abbrev=] --dirty[=]
 
 DESCRIPTION
@@ -27,7 +27,7 @@ see the -a and -s options to linkgit:git-tag[1].
 OPTIONS
 ---
 ...::
-   Commit-ish object names to describe.
+   Commit-ish object names to describe.  Defaults to HEAD if omitted.
 
 --dirty[=]::
Describe the working tree.
diff --git a/builtin/describe.c b/builtin/describe.c
index ce36032b1f..0e31ac5cb9 100644
--- a/builtin/describe.c
+++ b/builtin/describe.c
@@ -443,10 +443,13 @@ int cmd_describe(int argc, const char **argv, const char 
*prefix)
if (pattern)
argv_array_pushf(&args, "--refs=refs/tags/%s", 
pattern);
}
-   while (*argv) {
-   argv_array_push(&args, *argv);
-   argv++;
-   }
+   if (argc)
+   while (*argv) {
+   argv_array_push(&args, *argv);
+   argv++;
+   }
+   else
+   argv_array_push(&args, "HEAD");
return cmd_name_rev(args.argc, args.argv, prefix);
}
 
diff --git a/t/t6120-describe.sh b/t/t6120-describe.sh
index 57d50156bb..bf52a0a1cc 100755
--- a/t/t6120-describe.sh
+++ b/t/t6120-describe.sh
@@ -115,6 +115,14 @@ check_describe e-3-* --first-parent --tags
 
 check_describe $(git rev-parse --short HEAD) --exact-match --always HEAD
 
+test_expect_success 'describe --contains defaults to HEAD without commit-ish' '
+   echo "A^0" >expect &&
+   git checkout A &&
+   test_when_finished "git checkout -" &&
+   git describe --contains >actual &&
+   test_cmp expect actual
+'
+
 : >err.expect
 check_describe A --all A^0
 test_expect_success 'no warning was displayed for A' '
-- 
2.5.0.416.g84b07b4

--
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 7/7] submodule: implement `module_clone` as a builtin helper

2015-08-21 Thread Jeff King
On Mon, Aug 17, 2015 at 05:22:03PM -0700, Stefan Beller wrote:

> +static int module_clone(int argc, const char **argv, const char *prefix)
> [...]
> + /* Redirect the worktree of the submodule in the superprojects config */
> + if (!is_absolute_path(sm_gitdir)) {
> + char *s = (char*)sm_gitdir;
> + strbuf_addf(&sb, "%s/%s", xgetcwd(), sm_gitdir);

Coverity noticed that this is a leak; xgetcwd actually returns a newly
allocated buffer. I think you just want:

  if (strbuf_getcwd(&sb))
die_errno("unable to get current working directory");
  strbuf_addf("/%s", sm_gitdir);

> + sm_gitdir = strbuf_detach(&sb, NULL);
> + strbuf_reset(&sb);

This reset is a noop after you've detached. It's not technically
documented, but I do not think it is reasonable for it to work any other
way. Maybe strbuf.h should make that promise.

> + strbuf_addf(&sb, "%s/%s", xgetcwd(), path);

Ditto on the xgetcwd issue here.

-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 v4 08/10] grep/pcre: support utf-8

2015-08-21 Thread Nguyễn Thái Ngọc Duy
In the previous change in this function, we add locale support for
single-byte encodings only. It looks like pcre only supports utf-* as
multibyte encodings, the others are left in the cold (which is
fine).

We need to enable PCRE_UTF8 so pcre can find character boundary
correctly. It's needed for case folding (when --ignore-case is used)
or '*', '+' or similar syntax is used.

The "has_non_ascii()" check is to be on the conservative side. If
there's non-ascii in the pattern, the searched content could still be
in utf-8, but we can treat it just like a byte stream and everything
should work. If we force utf-8 based on locale only and pcre validates
utf-8 and the file content is in non-utf8 encoding, things break.

Noticed-by: Plamen Totev 
Helped-by: Plamen Totev 
Signed-off-by: Nguyễn Thái Ngọc Duy 
---
 grep.c  |  2 ++
 t/t7812-grep-icase-non-ascii.sh | 15 +++
 2 files changed, 17 insertions(+)

diff --git a/grep.c b/grep.c
index f0fbf99..07621c1 100644
--- a/grep.c
+++ b/grep.c
@@ -329,6 +329,8 @@ static void compile_pcre_regexp(struct grep_pat *p, const 
struct grep_opt *opt)
p->pcre_tables = pcre_maketables();
options |= PCRE_CASELESS;
}
+   if (is_utf8_locale() && has_non_ascii(p->pattern))
+   options |= PCRE_UTF8;
 
p->pcre_regexp = pcre_compile(p->pattern, options, &error, &erroffset,
  p->pcre_tables);
diff --git a/t/t7812-grep-icase-non-ascii.sh b/t/t7812-grep-icase-non-ascii.sh
index aba6b15..8896410 100755
--- a/t/t7812-grep-icase-non-ascii.sh
+++ b/t/t7812-grep-icase-non-ascii.sh
@@ -20,6 +20,21 @@ test_expect_success REGEX_LOCALE 'grep literal string, no 
-F' '
git grep -i "TILRAUN: HALLÓ HEIMUR!"
 '
 
+test_expect_success GETTEXT_LOCALE,LIBPCRE 'grep pcre utf-8 icase' '
+   git grep --perl-regexp"TILRAUN: H.lló Heimur!" &&
+   git grep --perl-regexp -i "TILRAUN: H.lló Heimur!" &&
+   git grep --perl-regexp -i "TILRAUN: H.LLÓ HEIMUR!"
+'
+
+test_expect_success GETTEXT_LOCALE,LIBPCRE 'grep pcre utf-8 string with "+"' '
+   printf "TILRAUN: Hallóó Heimur!" >file2 &&
+   git add file2 &&
+   git grep -l --perl-regexp "TILRAUN: H.lló+ Heimur!" >actual &&
+   echo file >expected &&
+   echo file2 >>expected &&
+   test_cmp expected actual
+'
+
 test_expect_success REGEX_LOCALE 'grep literal string, with -F' '
git grep --debug -i -F "TILRAUN: Halló Heimur!"  2>&1 >/dev/null |
 grep fixed >debug1 &&
-- 
2.3.0.rc1.137.g477eb31

--
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 v4 10/10] diffcore-pickaxe: support case insensitive match on non-ascii

2015-08-21 Thread Nguyễn Thái Ngọc Duy
Similar to the "grep -F -i" case, we can't use kws on icase search
outside ascii range, so we quote the string and pass it to regcomp as
a basic regexp and let regex engine deal with case sensitivity.

The new test is put in t7812 instead of t4209-log-pickaxe because
lib-gettext.sh might cause problems elsewhere, probably..

Noticed-by: Plamen Totev 
Signed-off-by: Nguyễn Thái Ngọc Duy 
---
 diffcore-pickaxe.c  | 11 +++
 t/t7812-grep-icase-non-ascii.sh |  7 +++
 2 files changed, 18 insertions(+)

diff --git a/diffcore-pickaxe.c b/diffcore-pickaxe.c
index 7a718fc..6946c15 100644
--- a/diffcore-pickaxe.c
+++ b/diffcore-pickaxe.c
@@ -7,6 +7,8 @@
 #include "diffcore.h"
 #include "xdiff-interface.h"
 #include "kwset.h"
+#include "commit.h"
+#include "quote.h"
 
 typedef int (*pickaxe_fn)(mmfile_t *one, mmfile_t *two,
  struct diff_options *o,
@@ -212,6 +214,15 @@ void diffcore_pickaxe(struct diff_options *o)
cflags |= REG_ICASE;
err = regcomp(®ex, needle, cflags);
regexp = ®ex;
+   } else if (DIFF_OPT_TST(o, PICKAXE_IGNORE_CASE) &&
+  has_non_ascii(needle)) {
+   struct strbuf sb = STRBUF_INIT;
+   int cflags = REG_NEWLINE | REG_ICASE;
+
+   basic_regex_quote_buf(&sb, needle);
+   err = regcomp(®ex, sb.buf, cflags);
+   strbuf_release(&sb);
+   regexp = ®ex;
} else {
kws = kwsalloc(DIFF_OPT_TST(o, PICKAXE_IGNORE_CASE)
   ? tolower_trans_tbl : NULL);
diff --git a/t/t7812-grep-icase-non-ascii.sh b/t/t7812-grep-icase-non-ascii.sh
index 8896410..a5475bb 100755
--- a/t/t7812-grep-icase-non-ascii.sh
+++ b/t/t7812-grep-icase-non-ascii.sh
@@ -61,4 +61,11 @@ test_expect_success REGEX_LOCALE 'grep string with regex, 
with -F' '
test_cmp expect2 debug2
 '
 
+test_expect_success REGEX_LOCALE 'pickaxe -i on non-ascii' '
+   git commit -m first &&
+   git log --format=%f -i -S"TILRAUN: HALLÓ HEIMUR!" >actual &&
+   echo first >expected &&
+   test_cmp expected actual
+'
+
 test_done
-- 
2.3.0.rc1.137.g477eb31

--
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 v4 09/10] diffcore-pickaxe: "share" regex error handling code

2015-08-21 Thread Nguyễn Thái Ngọc Duy
There's another regcomp code block coming in this function. By moving
the error handling code out of this block, we don't have to add the
same error handling code in the new block.

Signed-off-by: Nguyễn Thái Ngọc Duy 
---
 diffcore-pickaxe.c | 16 
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/diffcore-pickaxe.c b/diffcore-pickaxe.c
index 185f86b..7a718fc 100644
--- a/diffcore-pickaxe.c
+++ b/diffcore-pickaxe.c
@@ -204,20 +204,13 @@ void diffcore_pickaxe(struct diff_options *o)
int opts = o->pickaxe_opts;
regex_t regex, *regexp = NULL;
kwset_t kws = NULL;
+   int err = 0;
 
if (opts & (DIFF_PICKAXE_REGEX | DIFF_PICKAXE_KIND_G)) {
-   int err;
int cflags = REG_EXTENDED | REG_NEWLINE;
if (DIFF_OPT_TST(o, PICKAXE_IGNORE_CASE))
cflags |= REG_ICASE;
err = regcomp(®ex, needle, cflags);
-   if (err) {
-   /* The POSIX.2 people are surely sick */
-   char errbuf[1024];
-   regerror(err, ®ex, errbuf, 1024);
-   regfree(®ex);
-   die("invalid regex: %s", errbuf);
-   }
regexp = ®ex;
} else {
kws = kwsalloc(DIFF_OPT_TST(o, PICKAXE_IGNORE_CASE)
@@ -225,6 +218,13 @@ void diffcore_pickaxe(struct diff_options *o)
kwsincr(kws, needle, strlen(needle));
kwsprep(kws);
}
+   if (err) {
+   /* The POSIX.2 people are surely sick */
+   char errbuf[1024];
+   regerror(err, ®ex, errbuf, 1024);
+   regfree(®ex);
+   die("invalid regex: %s", errbuf);
+   }
 
/* Might want to warn when both S and G are on; I don't care... */
pickaxe(&diff_queued_diff, o, regexp, kws,
-- 
2.3.0.rc1.137.g477eb31

--
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 v4 07/10] gettext: add is_utf8_locale()

2015-08-21 Thread Nguyễn Thái Ngọc Duy
This function returns true if git is running under an UTF-8
locale. pcre in the next patch will need this.

is_encoding_utf8() is used instead of strcmp() to catch both "utf-8"
and "utf8" suffixes.

When built with no gettext support, we peek in several env variables
to detect UTF-8. pcre library might support utf-8 even if libc is
built without locale support.. The peeking code is a copy from
compat/regex/regcomp.c

Helped-by: Ævar Arnfjörð Bjarmason 
Signed-off-by: Nguyễn Thái Ngọc Duy 
---
 gettext.c | 24 ++--
 gettext.h |  1 +
 2 files changed, 23 insertions(+), 2 deletions(-)

diff --git a/gettext.c b/gettext.c
index a268a2c..db727ea 100644
--- a/gettext.c
+++ b/gettext.c
@@ -18,6 +18,8 @@
 #  endif
 #endif
 
+static const char *charset;
+
 /*
  * Guess the user's preferred languages from the value in LANGUAGE environment
  * variable and LC_MESSAGES locale category if NO_GETTEXT is not defined.
@@ -65,7 +67,6 @@ static int test_vsnprintf(const char *fmt, ...)
return ret;
 }
 
-static const char *charset;
 static void init_gettext_charset(const char *domain)
 {
/*
@@ -172,8 +173,27 @@ int gettext_width(const char *s)
 {
static int is_utf8 = -1;
if (is_utf8 == -1)
-   is_utf8 = !strcmp(charset, "UTF-8");
+   is_utf8 = is_utf8_locale();
 
return is_utf8 ? utf8_strwidth(s) : strlen(s);
 }
 #endif
+
+int is_utf8_locale(void)
+{
+#ifdef NO_GETTEXT
+   if (!charset) {
+   const char *env = getenv("LC_ALL");
+   if (!env || !*env)
+   env = getenv("LC_CTYPE");
+   if (!env || !*env)
+   env = getenv("LANG");
+   if (!env)
+   env = "";
+   if (strchr(env, '.'))
+   env = strchr(env, '.') + 1;
+   charset = xstrdup(env);
+   }
+#endif
+   return is_encoding_utf8(charset);
+}
diff --git a/gettext.h b/gettext.h
index 33696a4..7eee64a 100644
--- a/gettext.h
+++ b/gettext.h
@@ -90,5 +90,6 @@ const char *Q_(const char *msgid, const char *plu, unsigned 
long n)
 #endif
 
 const char *get_preferred_languages(void);
+extern int is_utf8_locale(void);
 
 #endif
-- 
2.3.0.rc1.137.g477eb31

--
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 v4 06/10] grep/pcre: prepare locale-dependent tables for icase matching

2015-08-21 Thread Nguyễn Thái Ngọc Duy
The default tables are usually built with C locale and only suitable
for LANG=C or similar.  This should make case insensitive search work
correctly for all single-byte charsets.

Signed-off-by: Nguyễn Thái Ngọc Duy 
---
 grep.c |  8 ++--
 grep.h |  1 +
 t/t7813-grep-icase-iso.sh (new +x) | 19 +++
 3 files changed, 26 insertions(+), 2 deletions(-)
 create mode 100755 t/t7813-grep-icase-iso.sh

diff --git a/grep.c b/grep.c
index 8fce54f..f0fbf99 100644
--- a/grep.c
+++ b/grep.c
@@ -324,11 +324,14 @@ static void compile_pcre_regexp(struct grep_pat *p, const 
struct grep_opt *opt)
int erroffset;
int options = PCRE_MULTILINE;
 
-   if (opt->ignore_case)
+   if (opt->ignore_case) {
+   if (has_non_ascii(p->pattern))
+   p->pcre_tables = pcre_maketables();
options |= PCRE_CASELESS;
+   }
 
p->pcre_regexp = pcre_compile(p->pattern, options, &error, &erroffset,
-   NULL);
+ p->pcre_tables);
if (!p->pcre_regexp)
compile_regexp_failed(p, error);
 
@@ -362,6 +365,7 @@ static void free_pcre_regexp(struct grep_pat *p)
 {
pcre_free(p->pcre_regexp);
pcre_free(p->pcre_extra_info);
+   pcre_free((void *)p->pcre_tables);
 }
 #else /* !USE_LIBPCRE */
 static void compile_pcre_regexp(struct grep_pat *p, const struct grep_opt *opt)
diff --git a/grep.h b/grep.h
index 95f197a..cee4357 100644
--- a/grep.h
+++ b/grep.h
@@ -48,6 +48,7 @@ struct grep_pat {
regex_t regexp;
pcre *pcre_regexp;
pcre_extra *pcre_extra_info;
+   const unsigned char *pcre_tables;
kwset_t kws;
unsigned fixed:1;
unsigned ignore_case:1;
diff --git a/t/t7813-grep-icase-iso.sh b/t/t7813-grep-icase-iso.sh
new file mode 100755
index 000..efef7fb
--- /dev/null
+++ b/t/t7813-grep-icase-iso.sh
@@ -0,0 +1,19 @@
+#!/bin/sh
+
+test_description='grep icase on non-English locales'
+
+. ./lib-gettext.sh
+
+test_expect_success GETTEXT_ISO_LOCALE 'setup' '
+   printf "TILRAUN: Hall� Heimur!" >file &&
+   git add file &&
+   LC_ALL="$is_IS_iso_locale" &&
+   export LC_ALL
+'
+
+test_expect_success GETTEXT_ISO_LOCALE,LIBPCRE 'grep pcre string' '
+   git grep --perl-regexp -i "TILRAUN: H.ll� Heimur!" &&
+   git grep --perl-regexp -i "TILRAUN: H.LL� HEIMUR!"
+'
+
+test_done
-- 
2.3.0.rc1.137.g477eb31

--
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 v4 05/10] grep/icase: avoid kwsset when -F is specified

2015-08-21 Thread Nguyễn Thái Ngọc Duy
Similar to the previous commit, we can't use kws on icase search
outside ascii range. But we can't simply pass the pattern to
regcomp/pcre like the previous commit because it may contain regex
special characters, so we need to quote the regex first.

To avoid misquote traps that could lead to undefined behavior, we
always stick to basic regex engine in this case. We don't need fancy
features for grepping a literal string anyway.

basic_regex_quote_buf() assumes that if the pattern is in a multibyte
encoding, ascii chars must be unambiguously encoded as single
bytes. This is true at least for UTF-8. For others, let's wait until
people yell up. Chances are nobody uses multibyte, non utf-8 charsets
any more..

Helped-by: René Scharfe 
Noticed-by: Plamen Totev 
Signed-off-by: Nguyễn Thái Ngọc Duy 
---
 grep.c  | 25 -
 quote.c | 37 +
 quote.h |  1 +
 t/t7812-grep-icase-non-ascii.sh | 26 ++
 4 files changed, 88 insertions(+), 1 deletion(-)

diff --git a/grep.c b/grep.c
index d795b0e..8fce54f 100644
--- a/grep.c
+++ b/grep.c
@@ -5,6 +5,7 @@
 #include "diff.h"
 #include "diffcore.h"
 #include "commit.h"
+#include "quote.h"
 
 static int grep_source_load(struct grep_source *gs);
 static int grep_source_is_binary(struct grep_source *gs);
@@ -397,6 +398,24 @@ static int is_fixed(const char *s, size_t len)
return 1;
 }
 
+static void compile_fixed_regexp(struct grep_pat *p, struct grep_opt *opt)
+{
+   struct strbuf sb = STRBUF_INIT;
+   int err;
+
+   basic_regex_quote_buf(&sb, p->pattern);
+   err = regcomp(&p->regexp, sb.buf, opt->regflags & ~REG_EXTENDED);
+   if (opt->debug)
+   fprintf(stderr, "fixed%s\n", sb.buf);
+   strbuf_release(&sb);
+   if (err) {
+   char errbuf[1024];
+   regerror(err, &p->regexp, errbuf, 1024);
+   regfree(&p->regexp);
+   compile_regexp_failed(p, errbuf);
+   }
+}
+
 static void compile_regexp(struct grep_pat *p, struct grep_opt *opt)
 {
int icase_non_ascii;
@@ -411,7 +430,11 @@ static void compile_regexp(struct grep_pat *p, struct 
grep_opt *opt)
if (!icase_non_ascii && is_fixed(p->pattern, p->patternlen))
p->fixed = 1;
else if (opt->fixed) {
-   p->fixed = 1;
+   p->fixed = !icase_non_ascii;
+   if (!p->fixed) {
+   compile_fixed_regexp(p, opt);
+   return;
+   }
} else
p->fixed = 0;
 
diff --git a/quote.c b/quote.c
index 7920e18..43a8057 100644
--- a/quote.c
+++ b/quote.c
@@ -439,3 +439,40 @@ void tcl_quote_buf(struct strbuf *sb, const char *src)
}
strbuf_addch(sb, '"');
 }
+
+void basic_regex_quote_buf(struct strbuf *sb, const char *src)
+{
+   char c;
+
+   if (*src == '^') {
+   /* only beginning '^' is special and needs quoting */
+   strbuf_addch(sb, '\\');
+   strbuf_addch(sb, *src++);
+   }
+   if (*src == '*')
+   /* beginning '*' is not special, no quoting */
+   strbuf_addch(sb, *src++);
+
+   while ((c = *src++)) {
+   switch (c) {
+   case '[':
+   case '.':
+   case '\\':
+   case '*':
+   strbuf_addch(sb, '\\');
+   strbuf_addch(sb, c);
+   break;
+
+   case '$':
+   /* only the end '$' is special and needs quoting */
+   if (*src == '\0')
+   strbuf_addch(sb, '\\');
+   strbuf_addch(sb, c);
+   break;
+
+   default:
+   strbuf_addch(sb, c);
+   break;
+   }
+   }
+}
diff --git a/quote.h b/quote.h
index 99e04d3..362d315 100644
--- a/quote.h
+++ b/quote.h
@@ -67,5 +67,6 @@ extern char *quote_path_relative(const char *in, const char 
*prefix,
 extern void perl_quote_buf(struct strbuf *sb, const char *src);
 extern void python_quote_buf(struct strbuf *sb, const char *src);
 extern void tcl_quote_buf(struct strbuf *sb, const char *src);
+extern void basic_regex_quote_buf(struct strbuf *sb, const char *src);
 
 #endif
diff --git a/t/t7812-grep-icase-non-ascii.sh b/t/t7812-grep-icase-non-ascii.sh
index 6eff490..aba6b15 100755
--- a/t/t7812-grep-icase-non-ascii.sh
+++ b/t/t7812-grep-icase-non-ascii.sh
@@ -20,4 +20,30 @@ test_expect_success REGEX_LOCALE 'grep literal string, no 
-F' '
git grep -i "TILRAUN: HALLÓ HEIMUR!"
 '
 
+test_expect_success REGEX_LOCALE 'grep literal string, with -F' '
+   git grep --debug -i -F "TILRAUN: Halló Heimur!"  2>&1 >/dev/null |
+grep fixed >debug1 &&
+   echo "fixedTILRAUN: Halló Heimur!" >expect1 &&
+   test_c

[PATCH v4 00/10] icase match on non-ascii

2015-08-21 Thread Nguyễn Thái Ngọc Duy
Sorry it took more than a month for a simple reroll. Free time (with
energy left) is rare these days. v4 adds system regex's icase support
detection and only runs tests in these cases. This should fix test
failures on Windows where compat regex does not support icase.

Diff from v3 below

diff --git a/t/t7812-grep-icase-non-ascii.sh b/t/t7812-grep-icase-non-ascii.sh
index d07fa20..a5475bb 100755
--- a/t/t7812-grep-icase-non-ascii.sh
+++ b/t/t7812-grep-icase-non-ascii.sh
@@ -11,7 +11,11 @@ test_expect_success GETTEXT_LOCALE 'setup' '
export LC_ALL
 '
 
-test_expect_success GETTEXT_LOCALE 'grep literal string, no -F' '
+test_have_prereq GETTEXT_LOCALE &&
+test-regex "HALLÓ" "Halló" ICASE &&
+test_set_prereq REGEX_LOCALE
+
+test_expect_success REGEX_LOCALE 'grep literal string, no -F' '
git grep -i "TILRAUN: Halló Heimur!" &&
git grep -i "TILRAUN: HALLÓ HEIMUR!"
 '
@@ -31,7 +35,7 @@ test_expect_success GETTEXT_LOCALE,LIBPCRE 'grep pcre utf-8 
string with "+"' '
test_cmp expected actual
 '
 
-test_expect_success GETTEXT_LOCALE 'grep literal string, with -F' '
+test_expect_success REGEX_LOCALE 'grep literal string, with -F' '
git grep --debug -i -F "TILRAUN: Halló Heimur!"  2>&1 >/dev/null |
 grep fixed >debug1 &&
echo "fixedTILRAUN: Halló Heimur!" >expect1 &&
@@ -43,7 +47,7 @@ test_expect_success GETTEXT_LOCALE 'grep literal string, with 
-F' '
test_cmp expect2 debug2
 '
 
-test_expect_success GETTEXT_LOCALE 'grep string with regex, with -F' '
+test_expect_success REGEX_LOCALE 'grep string with regex, with -F' '
printf "^*TILR^AUN:.* \\Halló \$He[]imur!\$" >file &&
 
git grep --debug -i -F "^*TILR^AUN:.* \\Halló \$He[]imur!\$" 2>&1 
>/dev/null |
@@ -57,7 +61,7 @@ test_expect_success GETTEXT_LOCALE 'grep string with regex, 
with -F' '
test_cmp expect2 debug2
 '
 
-test_expect_success GETTEXT_LOCALE 'pickaxe -i on non-ascii' '
+test_expect_success REGEX_LOCALE 'pickaxe -i on non-ascii' '
git commit -m first &&
git log --format=%f -i -S"TILRAUN: HALLÓ HEIMUR!" >actual &&
echo first >expected &&
diff --git a/test-regex.c b/test-regex.c
index 0dc598e..3b5641c 100644
--- a/test-regex.c
+++ b/test-regex.c
@@ -1,19 +1,63 @@
 #include "git-compat-util.h"
+#include "gettext.h"
+
+struct reg_flag {
+   const char *name;
+   int flag;
+};
+
+static struct reg_flag reg_flags[] = {
+   { "EXTENDED",REG_EXTENDED   },
+   { "NEWLINE", REG_NEWLINE},
+   { "ICASE",   REG_ICASE  },
+   { "NOTBOL",  REG_NOTBOL },
+#ifdef REG_STARTEND
+   { "STARTEND",REG_STARTEND   },
+#endif
+   { NULL, 0 }
+};
 
 int main(int argc, char **argv)
 {
-   char *pat = "[^={} \t]+";
-   char *str = "={}\nfred";
+   const char *pat;
+   const char *str;
+   int flags = 0;
regex_t r;
regmatch_t m[1];
 
-   if (regcomp(&r, pat, REG_EXTENDED | REG_NEWLINE))
+   if (argc == 1) {
+   /* special case, bug check */
+   pat = "[^={} \t]+";
+   str = "={}\nfred";
+   flags = REG_EXTENDED | REG_NEWLINE;
+   } else {
+   argv++;
+   pat = *argv++;
+   str = *argv++;
+   while (*argv) {
+   struct reg_flag *rf;
+   for (rf = reg_flags; rf->name; rf++)
+   if (!strcmp(*argv, rf->name)) {
+   flags |= rf->flag;
+   break;
+   }
+   if (!rf->name)
+   die("do not recognize %s", *argv);
+   argv++;
+   }
+   git_setup_gettext();
+   }
+
+   if (regcomp(&r, pat, flags))
die("failed regcomp() for pattern '%s'", pat);
-   if (regexec(&r, str, 1, m, 0))
-   die("no match of pattern '%s' to string '%s'", pat, str);
+   if (regexec(&r, str, 1, m, 0)) {
+   if (argc == 1)
+   die("no match of pattern '%s' to string '%s'", pat, 
str);
+   return 1;
+   }
 
/* http://sourceware.org/bugzilla/show_bug.cgi?id=3957  */
-   if (m[0].rm_so == 3) /* matches '\n' when it should not */
+   if (argc == 1 && m[0].rm_so == 3) /* matches '\n' when it should not */
die("regex bug confirmed: re-build git with NO_REGEX=1");
 
exit(0);
-- 
2.3.0.rc1.137.g477eb31

--
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 v4 01/10] grep: allow -F -i combination

2015-08-21 Thread Nguyễn Thái Ngọc Duy
-F means "no regex", not "case sensitive" so it should not override -i

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

diff --git a/builtin/grep.c b/builtin/grep.c
index d04f440..2d392e9 100644
--- a/builtin/grep.c
+++ b/builtin/grep.c
@@ -806,7 +806,7 @@ int cmd_grep(int argc, const char **argv, const char 
*prefix)
 
if (!opt.pattern_list)
die(_("no pattern given."));
-   if (!opt.fixed && opt.ignore_case)
+   if (opt.ignore_case)
opt.regflags |= REG_ICASE;
 
compile_grep_patterns(&opt);
-- 
2.3.0.rc1.137.g477eb31

--
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 v4 03/10] test-regex: expose full regcomp() to the command line

2015-08-21 Thread Nguyễn Thái Ngọc Duy
Signed-off-by: Nguyễn Thái Ngọc Duy 
---
 test-regex.c | 56 ++--
 1 file changed, 50 insertions(+), 6 deletions(-)

diff --git a/test-regex.c b/test-regex.c
index 0dc598e..3b5641c 100644
--- a/test-regex.c
+++ b/test-regex.c
@@ -1,19 +1,63 @@
 #include "git-compat-util.h"
+#include "gettext.h"
+
+struct reg_flag {
+   const char *name;
+   int flag;
+};
+
+static struct reg_flag reg_flags[] = {
+   { "EXTENDED",REG_EXTENDED   },
+   { "NEWLINE", REG_NEWLINE},
+   { "ICASE",   REG_ICASE  },
+   { "NOTBOL",  REG_NOTBOL },
+#ifdef REG_STARTEND
+   { "STARTEND",REG_STARTEND   },
+#endif
+   { NULL, 0 }
+};
 
 int main(int argc, char **argv)
 {
-   char *pat = "[^={} \t]+";
-   char *str = "={}\nfred";
+   const char *pat;
+   const char *str;
+   int flags = 0;
regex_t r;
regmatch_t m[1];
 
-   if (regcomp(&r, pat, REG_EXTENDED | REG_NEWLINE))
+   if (argc == 1) {
+   /* special case, bug check */
+   pat = "[^={} \t]+";
+   str = "={}\nfred";
+   flags = REG_EXTENDED | REG_NEWLINE;
+   } else {
+   argv++;
+   pat = *argv++;
+   str = *argv++;
+   while (*argv) {
+   struct reg_flag *rf;
+   for (rf = reg_flags; rf->name; rf++)
+   if (!strcmp(*argv, rf->name)) {
+   flags |= rf->flag;
+   break;
+   }
+   if (!rf->name)
+   die("do not recognize %s", *argv);
+   argv++;
+   }
+   git_setup_gettext();
+   }
+
+   if (regcomp(&r, pat, flags))
die("failed regcomp() for pattern '%s'", pat);
-   if (regexec(&r, str, 1, m, 0))
-   die("no match of pattern '%s' to string '%s'", pat, str);
+   if (regexec(&r, str, 1, m, 0)) {
+   if (argc == 1)
+   die("no match of pattern '%s' to string '%s'", pat, 
str);
+   return 1;
+   }
 
/* http://sourceware.org/bugzilla/show_bug.cgi?id=3957  */
-   if (m[0].rm_so == 3) /* matches '\n' when it should not */
+   if (argc == 1 && m[0].rm_so == 3) /* matches '\n' when it should not */
die("regex bug confirmed: re-build git with NO_REGEX=1");
 
exit(0);
-- 
2.3.0.rc1.137.g477eb31

--
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 v4 04/10] grep/icase: avoid kwsset on literal non-ascii strings

2015-08-21 Thread Nguyễn Thái Ngọc Duy
When we detect the pattern is just a literal string, we avoid heavy
regex engine and use fast substring search implemented in kwsset.c.
But kws uses git-ctype which is locale-independent so it does not know
how to fold case properly outside ascii range. Let regcomp or pcre
take care of this case instead. Slower, but accurate.

Helped-by: René Scharfe 
Noticed-by: Plamen Totev 
Signed-off-by: Nguyễn Thái Ngọc Duy 
---
 grep.c   |  7 ++-
 t/t7812-grep-icase-non-ascii.sh (new +x) | 23 +++
 2 files changed, 29 insertions(+), 1 deletion(-)
 create mode 100755 t/t7812-grep-icase-non-ascii.sh

diff --git a/grep.c b/grep.c
index bd32f66..d795b0e 100644
--- a/grep.c
+++ b/grep.c
@@ -4,6 +4,7 @@
 #include "xdiff-interface.h"
 #include "diff.h"
 #include "diffcore.h"
+#include "commit.h"
 
 static int grep_source_load(struct grep_source *gs);
 static int grep_source_is_binary(struct grep_source *gs);
@@ -398,12 +399,16 @@ static int is_fixed(const char *s, size_t len)
 
 static void compile_regexp(struct grep_pat *p, struct grep_opt *opt)
 {
+   int icase_non_ascii;
int err;
 
p->word_regexp = opt->word_regexp;
p->ignore_case = opt->ignore_case;
+   icase_non_ascii =
+   (opt->regflags & REG_ICASE || p->ignore_case) &&
+   has_non_ascii(p->pattern);
 
-   if (is_fixed(p->pattern, p->patternlen))
+   if (!icase_non_ascii && is_fixed(p->pattern, p->patternlen))
p->fixed = 1;
else if (opt->fixed) {
p->fixed = 1;
diff --git a/t/t7812-grep-icase-non-ascii.sh b/t/t7812-grep-icase-non-ascii.sh
new file mode 100755
index 000..6eff490
--- /dev/null
+++ b/t/t7812-grep-icase-non-ascii.sh
@@ -0,0 +1,23 @@
+#!/bin/sh
+
+test_description='grep icase on non-English locales'
+
+. ./lib-gettext.sh
+
+test_expect_success GETTEXT_LOCALE 'setup' '
+   printf "TILRAUN: Halló Heimur!" >file &&
+   git add file &&
+   LC_ALL="$is_IS_locale" &&
+   export LC_ALL
+'
+
+test_have_prereq GETTEXT_LOCALE &&
+test-regex "HALLÓ" "Halló" ICASE &&
+test_set_prereq REGEX_LOCALE
+
+test_expect_success REGEX_LOCALE 'grep literal string, no -F' '
+   git grep -i "TILRAUN: Halló Heimur!" &&
+   git grep -i "TILRAUN: HALLÓ HEIMUR!"
+'
+
+test_done
-- 
2.3.0.rc1.137.g477eb31

--
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 v4 02/10] grep: break down an "if" stmt in preparation for next changes

2015-08-21 Thread Nguyễn Thái Ngọc Duy
Signed-off-by: Nguyễn Thái Ngọc Duy 
---
 grep.c | 6 --
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/grep.c b/grep.c
index b58c7c6..bd32f66 100644
--- a/grep.c
+++ b/grep.c
@@ -403,9 +403,11 @@ static void compile_regexp(struct grep_pat *p, struct 
grep_opt *opt)
p->word_regexp = opt->word_regexp;
p->ignore_case = opt->ignore_case;
 
-   if (opt->fixed || is_fixed(p->pattern, p->patternlen))
+   if (is_fixed(p->pattern, p->patternlen))
p->fixed = 1;
-   else
+   else if (opt->fixed) {
+   p->fixed = 1;
+   } else
p->fixed = 0;
 
if (p->fixed) {
-- 
2.3.0.rc1.137.g477eb31

--
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/3] format_config: simplify buffer handling

2015-08-21 Thread SZEDER Gábor


Quoting Jeff King :


When formatting a config value into a strbuf, we may end
up stringifying it into a fixed-size buffer using sprintf,
and then copying that buffer into the strbuf. We can
eliminate the middle-man (and drop some calls to sprintf!)
by writing directly to the strbuf.

The reason it was written this way in the first place is
that we need to know before writing the value whether to
insert a delimiter. Instead of delaying the write of the
value, we speculatively write the delimiter, and roll it
back in the single case that cares.

Signed-off-by: Jeff King 
---
I admit the rollback is a little gross.


Indeed it is, but I'm for it, as it gets rit of so much more
other grossness, i.e. the fixed-size buffer and vptr stuff
and the two must_do_this variables.



builtin/config.c | 38 --
1 file changed, 16 insertions(+), 22 deletions(-)

diff --git a/builtin/config.c b/builtin/config.c
index 91aa56f..04befce 100644
--- a/builtin/config.c
+++ b/builtin/config.c
@@ -111,41 +111,35 @@ static int format_config(struct strbuf *buf,  
const char *key_, const char *value

if (show_keys)
strbuf_addstr(buf, key_);
if (!omit_values) {
-   int must_free_vptr = 0;
-   int must_add_delim = show_keys;
-   char value[256];
-   const char *vptr = value;
+   if (show_keys)
+   strbuf_addch(buf, key_delim);

if (types == TYPE_INT)
-   sprintf(value, "%"PRId64,
-   git_config_int64(key_, value_ ? value_ : ""));
+   strbuf_addf(buf, "%"PRId64,
+   git_config_int64(key_, value_ ? value_ : 
""));
else if (types == TYPE_BOOL)
-   vptr = git_config_bool(key_, value_) ? "true" : "false";
+   strbuf_addstr(buf, git_config_bool(key_, value_) ?
+ "true" : "false");
else if (types == TYPE_BOOL_OR_INT) {
int is_bool, v;
v = git_config_bool_or_int(key_, value_, &is_bool);
if (is_bool)
-   vptr = v ? "true" : "false";
+   strbuf_addstr(buf, v ? "true" : "false");
else
-   sprintf(value, "%d", v);
+   strbuf_addf(buf, "%d", v);
} else if (types == TYPE_PATH) {
-   if (git_config_pathname(&vptr, key_, value_) < 0)
+   const char *v;
+   if (git_config_pathname(&v, key_, value_) < 0)
return -1;
-   must_free_vptr = 1;
+   strbuf_addstr(buf, v);
+   free((char *)v);
} else if (value_) {
-   vptr = value_;
+   strbuf_addstr(buf, value_);
} else {
-   /* Just show the key name */
-   vptr = "";
-   must_add_delim = 0;
+   /* Just show the key name; back out delimiter */
+   if (show_keys)
+   strbuf_setlen(buf, buf->len - 1);
}
-
-   if (must_add_delim)
-   strbuf_addch(buf, key_delim);
-   strbuf_addstr(buf, vptr);
-
-   if (must_free_vptr)
-   free((char *)vptr);
}
strbuf_addch(buf, term);
return 0;
--
2.5.0.680.g69e7703


--
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: Unable to create temporary file '/var/git/tmv3-target-overlay.git/shallow_Un8ZOR': Permission denied

2015-08-21 Thread Joakim Tjernlund
On Fri, 2015-08-21 at 13:36 +0200, Joakim Tjernlund wrote:
> I cannot push:
> # > git push origin
> Login for jo...@git.transmode.se
> Password: 
> Counting objects: 7, done.
> Delta compression using up to 4 threads.
> Compressing objects: 100% (7/7), done.
> Writing objects: 100% (7/7), 13.73 KiB | 0 bytes/s, done.
> Total 7 (delta 4), reused 0 (delta 0)
> fatal: Unable to create temporary file 
> '/var/git/tmv3-target-overlay.git/shallow_Un8ZOR': Permission denied
> fatal: The remote end hung up unexpectedly
> fatal: The remote end hung up unexpectedly
> cu-km022 tmv3-target-overlay # ls -l
> total 0
> drwxr-xr-x 1 root root  72 Aug 19 17:59 ./
> drwxr-xr-x 1 root root  38 Aug 19 17:59 ../
> drwxr-xr-x 1 root root 216 Aug 21 13:07 .git/
> drwxr-xr-x 1 root root  22 Aug 19 17:59 metadata/
> drwxr-xr-x 1 root root  58 Aug 19 18:27 profiles/
> drwxr-xr-x 1 root root  74 Aug 19 17:59 sys-apps/
> drwxr-xr-x 1 root root  42 Aug 19 17:59 sys-libs/
> 
> On server I have:
> # >ls -la
> total 24
> dr-xr-sr-x   6 apache tm-3000  123 Jun 10 15:25 .
> drwxr-xr-x  36 root   root4096 Jun 25 11:11 ..
> -r--r--r--   1 root   tm-3000  263 Jun 10 15:18 config
> -r--r--r--   1 apache tm-3000   73 Jun 10 15:18 description
> -rw-r--r--   1 root   tm-30000 Jun 10 15:25 git-daemon-export-ok
> -r--r--r--   1 apache tm-3000   23 Jun 10 15:18 HEAD
> drwxr-sr-x   2 root   tm-3000 4096 Jun 10 15:18 hooks
> drwxrwsr-x   2 apache tm-3000   20 Jun 10 15:18 info
> drwxrwsr-x 135 apache tm-3000 4096 Aug 20 19:07 objects
> drwxrwsr-x   4 apache tm-3000   29 Jun 10 15:18 refs
> 
> 
> I suspect this is because no one is allowed to write the repos top dir.
> It would be much better if git allowed a tmp dir inside the repo and used 
> that 
> for push etc.
> Meanwhile, is there some workaround I can use?

This error seems to only affect shallow clones.
Forgot, git version 2.4.6

 Jocke
--
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


Unable to create temporary file '/var/git/tmv3-target-overlay.git/shallow_Un8ZOR': Permission denied

2015-08-21 Thread Joakim Tjernlund
I cannot push:
# > git push origin
Login for jo...@git.transmode.se
Password: 
Counting objects: 7, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (7/7), done.
Writing objects: 100% (7/7), 13.73 KiB | 0 bytes/s, done.
Total 7 (delta 4), reused 0 (delta 0)
fatal: Unable to create temporary file 
'/var/git/tmv3-target-overlay.git/shallow_Un8ZOR': Permission denied
fatal: The remote end hung up unexpectedly
fatal: The remote end hung up unexpectedly
cu-km022 tmv3-target-overlay # ls -l
total 0
drwxr-xr-x 1 root root  72 Aug 19 17:59 ./
drwxr-xr-x 1 root root  38 Aug 19 17:59 ../
drwxr-xr-x 1 root root 216 Aug 21 13:07 .git/
drwxr-xr-x 1 root root  22 Aug 19 17:59 metadata/
drwxr-xr-x 1 root root  58 Aug 19 18:27 profiles/
drwxr-xr-x 1 root root  74 Aug 19 17:59 sys-apps/
drwxr-xr-x 1 root root  42 Aug 19 17:59 sys-libs/

On server I have:
# >ls -la
total 24
dr-xr-sr-x   6 apache tm-3000  123 Jun 10 15:25 .
drwxr-xr-x  36 root   root4096 Jun 25 11:11 ..
-r--r--r--   1 root   tm-3000  263 Jun 10 15:18 config
-r--r--r--   1 apache tm-3000   73 Jun 10 15:18 description
-rw-r--r--   1 root   tm-30000 Jun 10 15:25 git-daemon-export-ok
-r--r--r--   1 apache tm-3000   23 Jun 10 15:18 HEAD
drwxr-sr-x   2 root   tm-3000 4096 Jun 10 15:18 hooks
drwxrwsr-x   2 apache tm-3000   20 Jun 10 15:18 info
drwxrwsr-x 135 apache tm-3000 4096 Aug 20 19:07 objects
drwxrwsr-x   4 apache tm-3000   29 Jun 10 15:18 refs


I suspect this is because no one is allowed to write the repos top dir.
It would be much better if git allowed a tmp dir inside the repo and used that 
for push etc.
Meanwhile, is there some workaround I can use?

 Jocke--
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] describe: make '--always' fallback work after '--exact-match' failed

2015-08-21 Thread SZEDER Gábor


Quoting Junio C Hamano :


SZEDER Gábor  writes:


'git describe [...] --always' should always show the unique abbreviated
object name as a fallback when the given commit cannot be described with
the given set of options, see da2478dbb0 (describe --always: fall back
to showing an abbreviated object name, 2008-03-02).

However, this is not the case when the combination '--exact-match
--always' is given and the commit cannot be described, because in such
cases 'git describe' errors out, as if '--always' were not given at all.

Respect '--always' and print the unique abbreviated object name instead
of erroring out when the commit cannot be described with '--exact-match
--always'.

Signed-off-by: SZEDER Gábor 


Well, that can be argued both ways.  Your patch introduces a
regression, as "--exact-match" is an instruction to error out when
no tag exactly matches, and you deliberately break that.


This patch doesn't break '--exact-match', in fact doesn't modify it at all
when it's on its own or combined with other options, but it makes
'--exact-match --always' finally work.

'git describe' errors out by default if it can't describe the given
commit.  So if a user wants an exact match or an error otherwise, then he
should not give '--always' at all, because that's the instruction to not
error out but give the abbreviated object name instead.

Why should '--exact-match' be any different from the other options that
tell 'git describe' what to use for the description?  Why should
'--always' not work with '--exact-match', when it works in the other
cases?

Consider '--contains': it should find a tag that comes after the given
commit or error out if such a tag doesn't exist.  Now, in current git.git:

  $ git describe --contains master
  fatal: cannot describe 'ff86faf2fa02bc21933c9e1dcc75c8d81b3e104a'
  $ git describe --contains --always master
  ff86faf2fa

Or the default behavior without any options: it should find a tag
reachable from the given commit or error out, but what if we pass in a
commit before the first tag?  It recommends '--always':

  $ git describe e83c516
  fatal: No tags can describe 'e83c5163316f89bfbde7d9ab23ca2e25604af290'.
  Try --always, or create some tags.
  $ git describe --always e83c516
  e83c516331



My knee-jerk reaction is that the most sensible way forward is to
make --exact-match and --always mutually incompatible.


That would be wrong, it's perfectly valid to ask for an exactly matching
tag or, if there is no such tag, the abbreviated object name as a
fallback.

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


  1   2   >