Re: [PATCH v2 09/11] parse-options.h: add macros for '--contains' option

2015-06-13 Thread karthik nayak
On Sun, Jun 14, 2015 at 11:43 AM, Christian Couder
 wrote:
> On Sat, Jun 13, 2015 at 10:18 PM, Karthik Nayak  wrote:
>> Add a macro for using the '--contains' option in parse-options.h
>> also include an optional '--with' option macro which performs the
>> same action as '--contains'.
>>
>> Make tag.c use this new macro
>>
>> Mentored-by: Christian Couder 
>> Mentored-by: Matthieu Moy 
>> Signed-off-by: Karthik Nayak 
>> ---
>>  builtin/tag.c   | 14 ++
>>  parse-options.h |  7 +++
>>  2 files changed, 9 insertions(+), 12 deletions(-)
>>
>> diff --git a/builtin/tag.c b/builtin/tag.c
>> index 2d6610a..767162e 100644
>> --- a/builtin/tag.c
>> +++ b/builtin/tag.c
>> @@ -595,23 +595,13 @@ int cmd_tag(int argc, const char **argv, const char 
>> *prefix)
>>
>> OPT_GROUP(N_("Tag listing options")),
>> OPT_COLUMN(0, "column", &colopts, N_("show tag list in 
>> columns")),
>> +   OPT_CONTAINS(&with_commit, N_("print only tags that contain 
>> the commit")),
>> +   OPT_WITH(&with_commit, N_("print only tags that contain the 
>> commit")),
>> {
>> OPTION_CALLBACK, 0, "sort", &tag_sort, N_("type"), 
>> N_("sort tags"),
>> PARSE_OPT_NONEG, parse_opt_sort
>> },
>> {
>> -   OPTION_CALLBACK, 0, "contains", &with_commit, 
>> N_("commit"),
>> -   N_("print only tags that contain the commit"),
>> -   PARSE_OPT_LASTARG_DEFAULT,
>> -   parse_opt_commit_object_name, (intptr_t)"HEAD",
>> -   },
>> -   {
>> -   OPTION_CALLBACK, 0, "with", &with_commit, 
>> N_("commit"),
>> -   N_("print only tags that contain the commit"),
>> -   PARSE_OPT_HIDDEN | PARSE_OPT_LASTARG_DEFAULT,
>
> The PARSE_OPT_HIDDEN flag is removed below. This means that "--with"
> will appear in the "git tag -h" output, which means that "--with"
> should appear in the documentation...
> The commit message may also want to tell that with is not hidden any more.
>

Yes! I will add that.

>> -   parse_opt_commit_object_name, (intptr_t)"HEAD",
>> -   },
>> -   {
>> OPTION_CALLBACK, 0, "points-at", &points_at, 
>> N_("object"),
>> N_("print only tags of the object"), 0, 
>> parse_opt_object_name
>> },
>> diff --git a/parse-options.h b/parse-options.h
>> index 8542d9c..d76e907 100644
>> --- a/parse-options.h
>> +++ b/parse-options.h
>> @@ -243,5 +243,12 @@ extern int parse_opt_noop_cb(const struct option *, 
>> const char *, int);
>> OPT_COLOR_FLAG(0, "color", (var), (h))
>>  #define OPT_COLUMN(s, l, v, h) \
>> { OPTION_CALLBACK, (s), (l), (v), N_("style"), (h), 
>> PARSE_OPT_OPTARG, parseopt_column_callback }
>> +#define _OPT_CONTAINS_OR_WITH(name, variable, help) \
>> +   { OPTION_CALLBACK, 0, name, (variable), N_("commit"), (help), \
>> + PARSE_OPT_LASTARG_DEFAULT, \
>> + parse_opt_commit_object_name, (intptr_t) "HEAD" \
>> +   }
>> +#define OPT_CONTAINS(v, h) _OPT_CONTAINS_OR_WITH("contains", v, h)
>> +#define OPT_WITH(v, h) _OPT_CONTAINS_OR_WITH("contains", v, h)
>
> Shouldn't it be "with" instead of "contains"?

Actually it wouldn't matter, but since I've removed the PARSE_OPT_HIDDEN flag
it would show 'contains' twice. Will change it to 'with'.

Thanks for the review.

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


Re: [PATCH v2 05/11] ref-filter: add parse_opt_merge_filter()

2015-06-13 Thread karthik nayak
On Sun, Jun 14, 2015 at 11:19 AM, Christian Couder
 wrote:
> On Sat, Jun 13, 2015 at 10:18 PM, Karthik Nayak  wrote:
>>
>> diff --git a/ref-filter.h b/ref-filter.h
>> index c2856b8..799e118 100644
>> --- a/ref-filter.h
>> +++ b/ref-filter.h
>> @@ -50,6 +50,18 @@ struct ref_filter_cbdata {
>> struct ref_filter *filter;
>>  };
>>
>> +/*  Macros for checking --merged and --no-merged options */
>> +#define OPT_NO_MERGED(filter, h) \
>> +   { OPTION_CALLBACK, 0, "no-merged", (filter), N_("commit"), (h), \
>> + PARSE_OPT_LASTARG_DEFAULT | PARSE_OPT_NONEG, \
>> + parse_opt_merge_filter, (intptr_t) "HEAD" \
>> +   }
>> +#define OPT_MERGED(filter, h) \
>> +   { OPTION_CALLBACK, 0, "merged", (filter), N_("commit"), (h), \
>> + PARSE_OPT_LASTARG_DEFAULT | PARSE_OPT_NONEG, \
>> + parse_opt_merge_filter, (intptr_t) "HEAD" \
>> +   }
>
> Could you reduce the redundancy in these 2 macros?

Yes, will do!

-- 
Regards,
Karthik Nayak
--
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 09/11] parse-options.h: add macros for '--contains' option

2015-06-13 Thread Christian Couder
On Sat, Jun 13, 2015 at 10:18 PM, Karthik Nayak  wrote:
> Add a macro for using the '--contains' option in parse-options.h
> also include an optional '--with' option macro which performs the
> same action as '--contains'.
>
> Make tag.c use this new macro
>
> Mentored-by: Christian Couder 
> Mentored-by: Matthieu Moy 
> Signed-off-by: Karthik Nayak 
> ---
>  builtin/tag.c   | 14 ++
>  parse-options.h |  7 +++
>  2 files changed, 9 insertions(+), 12 deletions(-)
>
> diff --git a/builtin/tag.c b/builtin/tag.c
> index 2d6610a..767162e 100644
> --- a/builtin/tag.c
> +++ b/builtin/tag.c
> @@ -595,23 +595,13 @@ int cmd_tag(int argc, const char **argv, const char 
> *prefix)
>
> OPT_GROUP(N_("Tag listing options")),
> OPT_COLUMN(0, "column", &colopts, N_("show tag list in 
> columns")),
> +   OPT_CONTAINS(&with_commit, N_("print only tags that contain 
> the commit")),
> +   OPT_WITH(&with_commit, N_("print only tags that contain the 
> commit")),
> {
> OPTION_CALLBACK, 0, "sort", &tag_sort, N_("type"), 
> N_("sort tags"),
> PARSE_OPT_NONEG, parse_opt_sort
> },
> {
> -   OPTION_CALLBACK, 0, "contains", &with_commit, 
> N_("commit"),
> -   N_("print only tags that contain the commit"),
> -   PARSE_OPT_LASTARG_DEFAULT,
> -   parse_opt_commit_object_name, (intptr_t)"HEAD",
> -   },
> -   {
> -   OPTION_CALLBACK, 0, "with", &with_commit, 
> N_("commit"),
> -   N_("print only tags that contain the commit"),
> -   PARSE_OPT_HIDDEN | PARSE_OPT_LASTARG_DEFAULT,

The PARSE_OPT_HIDDEN flag is removed below. This means that "--with"
will appear in the "git tag -h" output, which means that "--with"
should appear in the documentation...
The commit message may also want to tell that with is not hidden any more.

> -   parse_opt_commit_object_name, (intptr_t)"HEAD",
> -   },
> -   {
> OPTION_CALLBACK, 0, "points-at", &points_at, 
> N_("object"),
> N_("print only tags of the object"), 0, 
> parse_opt_object_name
> },
> diff --git a/parse-options.h b/parse-options.h
> index 8542d9c..d76e907 100644
> --- a/parse-options.h
> +++ b/parse-options.h
> @@ -243,5 +243,12 @@ extern int parse_opt_noop_cb(const struct option *, 
> const char *, int);
> OPT_COLOR_FLAG(0, "color", (var), (h))
>  #define OPT_COLUMN(s, l, v, h) \
> { OPTION_CALLBACK, (s), (l), (v), N_("style"), (h), PARSE_OPT_OPTARG, 
> parseopt_column_callback }
> +#define _OPT_CONTAINS_OR_WITH(name, variable, help) \
> +   { OPTION_CALLBACK, 0, name, (variable), N_("commit"), (help), \
> + PARSE_OPT_LASTARG_DEFAULT, \
> + parse_opt_commit_object_name, (intptr_t) "HEAD" \
> +   }
> +#define OPT_CONTAINS(v, h) _OPT_CONTAINS_OR_WITH("contains", v, h)
> +#define OPT_WITH(v, h) _OPT_CONTAINS_OR_WITH("contains", v, h)

Shouldn't it be "with" instead of "contains"?
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v2 05/11] ref-filter: add parse_opt_merge_filter()

2015-06-13 Thread Christian Couder
On Sat, Jun 13, 2015 at 10:18 PM, Karthik Nayak  wrote:
>
> diff --git a/ref-filter.h b/ref-filter.h
> index c2856b8..799e118 100644
> --- a/ref-filter.h
> +++ b/ref-filter.h
> @@ -50,6 +50,18 @@ struct ref_filter_cbdata {
> struct ref_filter *filter;
>  };
>
> +/*  Macros for checking --merged and --no-merged options */
> +#define OPT_NO_MERGED(filter, h) \
> +   { OPTION_CALLBACK, 0, "no-merged", (filter), N_("commit"), (h), \
> + PARSE_OPT_LASTARG_DEFAULT | PARSE_OPT_NONEG, \
> + parse_opt_merge_filter, (intptr_t) "HEAD" \
> +   }
> +#define OPT_MERGED(filter, h) \
> +   { OPTION_CALLBACK, 0, "merged", (filter), N_("commit"), (h), \
> + PARSE_OPT_LASTARG_DEFAULT | PARSE_OPT_NONEG, \
> + parse_opt_merge_filter, (intptr_t) "HEAD" \
> +   }

Could you reduce the redundancy in these 2 macros?
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v7 2/5] setup: sanity check file size in read_gitfile_gently

2015-06-13 Thread Eric Sunshine
On Tue, Jun 9, 2015 at 2:24 PM, Erik Elfström  wrote:
> read_gitfile_gently will allocate a buffer to fit the entire file that
> should be read. Add a sanity check of the file size before opening to
> avoid allocating a potentially huge amount of memory if we come across
> a large file that someone happened to name ".git". The limit is set to
> a sufficiently unreasonable size that should never be exceeded by a
> genuine .git file.
>
> Signed-off-by: Erik Elfström 
> ---
> diff --git a/setup.c b/setup.c
> index 4748b63..e76955e 100644
> --- a/setup.c
> +++ b/setup.c
> @@ -414,6 +414,7 @@ static void update_linked_gitdir(const char *gitfile, 
> const char *gitdir)
>   */
>  const char *read_gitfile_gently(const char *path, int *return_error_code)
>  {
> +   static const int one_MB = 1 << 20;

This variable name doesn't convey much about its purpose, and
introduces a bit of maintenance burden if the limit is some day
changed. Perhaps "sane_size_limit" or something even more descriptive
(and/or terse) would be better.

> int error_code = 0;
> char *buf = NULL;
> char *dir = NULL;
> @@ -430,6 +431,10 @@ const char *read_gitfile_gently(const char *path, int 
> *return_error_code)
> error_code = READ_GITFILE_ERR_NOT_A_FILE;
> goto cleanup_return;
> }
> +   if (st.st_size > one_MB) {
> +   error_code = READ_GITFILE_ERR_TOO_LARGE;
> +   goto cleanup_return;
> +   }
> fd = open(path, O_RDONLY);
> if (fd < 0) {
> error_code = READ_GITFILE_ERR_OPEN_FAILED;
> @@ -489,6 +494,8 @@ cleanup_return:
> return NULL;
> case READ_GITFILE_ERR_OPEN_FAILED:
> die_errno("Error opening '%s'", path);
> +   case READ_GITFILE_ERR_TOO_LARGE:
> +   die("Too large to be a .git file: '%s'", path);
> case READ_GITFILE_ERR_READ_FAILED:
> die("Error reading %s", path);
> case READ_GITFILE_ERR_INVALID_FORMAT:
> --
> 2.4.3.373.gc496bfb
--
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: Failed assertion in pathspec.c

2015-06-13 Thread Duy Nguyen
On Sun, Jun 14, 2015 at 12:18 AM, Sami Boukortt  wrote:
> git: pathspec.c:317: prefix_pathspec: Assertion `item->nowildcard_len
> <= item->len && item->prefix <= item->len' failed.

Known issue, but no one stepped up to fix it yet

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


Re: [PATCH/RFCv5 3/3] git rebase -i: add static check for commands and SHA-1

2015-06-13 Thread Remi Galan Alfonso
Matthieu Moy  writes:
> Remi Galan Alfonso  writes:
> 
> > It is mainly because here the SHA-1 is a long one (40 chars)
> 
> OK, but then the minimum would be to add a comment saying that.
> 
> Now, this makes me wonder why you are doing the check after the sha1
> expansion and not before. Also, when running `git bisect --edit-todo`, I
> do get the short sha1. So, there's a piece of code doing what you want
> somewhere already. You may want to use it.

Originally I did the whole checking after the expansion because I
though that it was a better idea to avoid doing it myself (Comparing
the whole SHA-1 instead of partial ones to find missing ones made more
sense for me since otherwise I would have to check if one is the
prefix of the other or expand to the same size before comparing).

However I agree that adding a comment would make things clearer. Will
probably do that.

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


[PATCH v2 05/10] parse_fetch: convert to use struct object_id

2015-06-13 Thread brian m. carlson
Convert the parse_fetch function to use struct object_id.  Remove the
strlen check as get_oid_hex will fail safely on receiving a too-short
NUL-terminated string.

Signed-off-by: brian m. carlson 
---
 remote-curl.c | 12 ++--
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/remote-curl.c b/remote-curl.c
index 80cb4c7..1709346 100644
--- a/remote-curl.c
+++ b/remote-curl.c
@@ -802,19 +802,19 @@ static void parse_fetch(struct strbuf *buf)
if (skip_prefix(buf->buf, "fetch ", &p)) {
const char *name;
struct ref *ref;
-   unsigned char old_sha1[20];
+   struct object_id old_oid;
 
-   if (strlen(p) < 40 || get_sha1_hex(p, old_sha1))
+   if (get_oid_hex(p, &old_oid))
die("protocol error: expected sha/ref, got 
%s'", p);
-   if (p[40] == ' ')
-   name = p + 41;
-   else if (!p[40])
+   if (p[GIT_SHA1_HEXSZ] == ' ')
+   name = p + GIT_SHA1_HEXSZ + 1;
+   else if (!p[GIT_SHA1_HEXSZ])
name = "";
else
die("protocol error: expected sha/ref, got 
%s'", p);
 
ref = alloc_ref(name);
-   hashcpy(ref->old_oid.hash, old_sha1);
+   oidcpy(&ref->old_oid, &old_oid);
 
*list = ref;
list = &ref->next;
-- 
2.4.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 v2 01/10] refs: convert some internal functions to use object_id

2015-06-13 Thread brian m. carlson
Convert several internal functions in refs.c to use struct object_id,
and use the GIT_SHA1_HEXSZ constants in parse_ref_line.

Signed-off-by: brian m. carlson 
---
 refs.c | 104 -
 1 file changed, 52 insertions(+), 52 deletions(-)

diff --git a/refs.c b/refs.c
index 26d1ac1..2087012 100644
--- a/refs.c
+++ b/refs.c
@@ -1158,7 +1158,7 @@ static const char PACKED_REFS_HEADER[] =
  * Return a pointer to the refname within the line (null-terminated),
  * or NULL if there was a problem.
  */
-static const char *parse_ref_line(struct strbuf *line, unsigned char *sha1)
+static const char *parse_ref_line(struct strbuf *line, struct object_id *oid)
 {
const char *ref;
 
@@ -1170,15 +1170,15 @@ static const char *parse_ref_line(struct strbuf *line, 
unsigned char *sha1)
 *  +1 (space in between hex and name)
 *  +1 (newline at the end of the line)
 */
-   if (line->len <= 42)
+   if (line->len <= GIT_SHA1_HEXSZ + 2)
return NULL;
 
-   if (get_sha1_hex(line->buf, sha1) < 0)
+   if (get_oid_hex(line->buf, oid) < 0)
return NULL;
-   if (!isspace(line->buf[40]))
+   if (!isspace(line->buf[GIT_SHA1_HEXSZ]))
return NULL;
 
-   ref = line->buf + 41;
+   ref = line->buf + GIT_SHA1_HEXSZ + 1;
if (isspace(*ref))
return NULL;
 
@@ -1223,7 +1223,7 @@ static void read_packed_refs(FILE *f, struct ref_dir *dir)
enum { PEELED_NONE, PEELED_TAGS, PEELED_FULLY } peeled = PEELED_NONE;
 
while (strbuf_getwholeline(&line, f, '\n') != EOF) {
-   unsigned char sha1[20];
+   struct object_id oid;
const char *refname;
const char *traits;
 
@@ -1236,17 +1236,17 @@ static void read_packed_refs(FILE *f, struct ref_dir 
*dir)
continue;
}
 
-   refname = parse_ref_line(&line, sha1);
+   refname = parse_ref_line(&line, &oid);
if (refname) {
int flag = REF_ISPACKED;
 
if (check_refname_format(refname, 
REFNAME_ALLOW_ONELEVEL)) {
if (!refname_is_safe(refname))
die("packed refname is dangerous: %s", 
refname);
-   hashclr(sha1);
+   oidclr(&oid);
flag |= REF_BAD_NAME | REF_ISBROKEN;
}
-   last = create_ref_entry(refname, sha1, flag, 0);
+   last = create_ref_entry(refname, oid.hash, flag, 0);
if (peeled == PEELED_FULLY ||
(peeled == PEELED_TAGS && starts_with(refname, 
"refs/tags/")))
last->flag |= REF_KNOWS_PEELED;
@@ -1257,8 +1257,8 @@ static void read_packed_refs(FILE *f, struct ref_dir *dir)
line.buf[0] == '^' &&
line.len == PEELED_LINE_LENGTH &&
line.buf[PEELED_LINE_LENGTH - 1] == '\n' &&
-   !get_sha1_hex(line.buf + 1, sha1)) {
-   hashcpy(last->u.value.peeled.hash, sha1);
+   !get_oid_hex(line.buf + 1, &oid)) {
+   oidcpy(&last->u.value.peeled, &oid);
/*
 * Regardless of what the file header said,
 * we definitely know the value of *this*
@@ -1352,7 +1352,7 @@ static void read_loose_refs(const char *dirname, struct 
ref_dir *dir)
strbuf_add(&refname, dirname, dirnamelen);
 
while ((de = readdir(d)) != NULL) {
-   unsigned char sha1[20];
+   struct object_id oid;
struct stat st;
int flag;
const char *refdir;
@@ -1374,27 +1374,27 @@ static void read_loose_refs(const char *dirname, struct 
ref_dir *dir)
  refname.len, 1));
} else {
if (*refs->name) {
-   hashclr(sha1);
+   oidclr(&oid);
flag = 0;
-   if (resolve_gitlink_ref(refs->name, 
refname.buf, sha1) < 0) {
-   hashclr(sha1);
+   if (resolve_gitlink_ref(refs->name, 
refname.buf, oid.hash) < 0) {
+   oidclr(&oid);
flag |= REF_ISBROKEN;
}
} else if (read_ref_full(refname.buf,
 RESOLVE_REF_READING,
-sha1, &flag)) {
-   hashclr(sha1);
+oid.hash, 

[PATCH v2 00/10] object_id part 2

2015-06-13 Thread brian m. carlson
This is another series of conversions to struct object_id.

This series converts more of the refs code and struct object to use
struct object_id.  It introduces an additional helper function,
has_object_file, which is the equivalent of has_sha1_file.  The name was
chosen to be slightly more logical than has_oid_file, although it can be
changed if desired.

The next-to-last patch in this series is the conversion of struct object
to use struct object_id.  This is a necessarily large patch because of
the large number of places this code is used.  That patch will most
likely be too large to make it through to the list, so this series is
available in the object-id-part2 branch from:

https://github.com/bk2204/git.git
https://git.crustytoothpaste.net/git/bmc/git.git

Changes from v1:
* Rebase on newer master.
* Drop parse_oid_hex.  It ended up not being very useful (only 4 uses
  over 47 patches) and a better version, like the one Michael Haggerty
  suggested, can be introduced later if it's beneficial.
* Fix the code that caused the httpd unit tests to fail.  This series
  passes the testsuite on each commit, including the httpd tests.
* Convert the remaining places touched by the first patch to use
  object_id.  These were split out into their own patches to keep
  patches to a reasonable size.  Some of these were in the original
  series, and some were not.
* Convert remote.c as well.  As part of the previous item, I went
  through remote.c and converted the places touched by the first patch,
  and realized that it was trivial to convert the rest of the file.
  This patch is at the end as we can get slightly better conversion by
  doing it after the conversion of struct object, meaning we can avoid
  making another pass later.  I blame Michael for the inspiration to do
  this. :-)

brian m. carlson (10):
  refs: convert some internal functions to use object_id
  sha1_file: introduce has_object_file helper.
  Convert struct ref to use object_id.
  add_sought_entry_mem: convert to struct object_id
  parse_fetch: convert to use struct object_id
  get_remote_heads: convert to struct object_id
  push_refs_with_export: convert to struct object_id
  ref_newer: convert to use struct object_id
  Convert struct object to object_id
  remote: convert functions to struct object_id

 archive.c|   6 +--
 bisect.c |  10 ++--
 branch.c |   2 +-
 builtin/blame.c  |  46 +-
 builtin/branch.c |   2 +-
 builtin/checkout.c   |  24 +-
 builtin/clone.c  |  18 +++
 builtin/commit-tree.c|   4 +-
 builtin/commit.c |   8 ++--
 builtin/describe.c   |  20 
 builtin/diff-tree.c  |  12 ++---
 builtin/diff.c   |  12 ++---
 builtin/fast-export.c|  34 +++---
 builtin/fetch-pack.c |  14 +++---
 builtin/fetch.c  |  54 ++---
 builtin/fmt-merge-msg.c  |   6 +--
 builtin/for-each-ref.c   |  12 ++---
 builtin/fsck.c   |  34 +++---
 builtin/grep.c   |   6 +--
 builtin/index-pack.c |  10 ++--
 builtin/log.c|  24 +-
 builtin/ls-remote.c  |   2 +-
 builtin/merge-base.c |   8 ++--
 builtin/merge-tree.c |   6 +--
 builtin/merge.c  |  60 
 builtin/name-rev.c   |  12 ++---
 builtin/notes.c  |   2 +-
 builtin/pack-objects.c   |  16 +++
 builtin/receive-pack.c   |   2 +-
 builtin/reflog.c |   4 +-
 builtin/remote.c |  12 ++---
 builtin/replace.c|   2 +-
 builtin/reset.c  |   6 +--
 builtin/rev-list.c   |  18 +++
 builtin/rev-parse.c  |   4 +-
 builtin/shortlog.c   |   2 +-
 builtin/show-branch.c|   8 ++--
 builtin/tag.c|   4 +-
 builtin/unpack-objects.c |  10 ++--
 bundle.c |  10 ++--
 cache-tree.c |   2 +-
 cache.h  |   3 ++
 combine-diff.c   |   4 +-
 commit.c |  32 ++---
 connect.c|  22 +
 decorate.c   |   2 +-
 diff-lib.c   |   2 +-
 fetch-pack.c |  24 +-
 fsck.c   |  10 ++--
 http-backend.c   |   2 +-
 http-push.c  |  88 +-
 http.c   |   2 +-
 line-log.c   |   6 +--
 list-objects.c   |   4 +-
 log-tree.c   |  32 ++---
 merge-blobs.c|   4 +-
 merge-recursive.c|  22 -
 merge.c  |   2 +-
 notes-merge.c|  24 +-
 object.c |   8 ++--
 object.h |   2 +-
 pack-bitmap-write.c  |  16 +++
 pack-bitmap.c|  34 +++---
 patch-ids.c  |   6 +--
 pretty.c |  18 +++
 refs.c   | 106 -
 remote-curl.c|  20 
 remote.c | 120 ++

[PATCH v2 08/10] ref_newer: convert to use struct object_id

2015-06-13 Thread brian m. carlson
Convert ref_newer and its caller to use struct object_id instead of
unsigned char *.

Signed-off-by: brian m. carlson 
---
 builtin/remote.c | 2 +-
 http-push.c  | 4 ++--
 remote.c | 8 
 remote.h | 2 +-
 4 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/builtin/remote.c b/builtin/remote.c
index fa4d04c..0efc388 100644
--- a/builtin/remote.c
+++ b/builtin/remote.c
@@ -411,7 +411,7 @@ static int get_push_ref_states(const struct ref 
*remote_refs,
else if (is_null_oid(&ref->old_oid))
info->status = PUSH_STATUS_CREATE;
else if (has_object_file(&ref->old_oid) &&
-ref_newer(ref->new_oid.hash, ref->old_oid.hash))
+ref_newer(&ref->new_oid, &ref->old_oid))
info->status = PUSH_STATUS_FASTFORWARD;
else
info->status = PUSH_STATUS_OUTOFDATE;
diff --git a/http-push.c b/http-push.c
index d054fdb..0e688a7 100644
--- a/http-push.c
+++ b/http-push.c
@@ -1899,8 +1899,8 @@ int main(int argc, char **argv)
!is_null_oid(&ref->old_oid) &&
!ref->force) {
if (!has_object_file(&ref->old_oid) ||
-   !ref_newer(ref->peer_ref->new_oid.hash,
-  ref->old_oid.hash)) {
+   !ref_newer(&ref->peer_ref->new_oid,
+  &ref->old_oid)) {
/*
 * We do not have the remote ref, or
 * we know that the remote ref is not
diff --git a/remote.c b/remote.c
index 0574120..cb85c3e 100644
--- a/remote.c
+++ b/remote.c
@@ -1626,7 +1626,7 @@ void set_ref_status_for_push(struct ref *remote_refs, int 
send_mirror,
else if 
(!lookup_commit_reference_gently(ref->old_oid.hash, 1) ||
 
!lookup_commit_reference_gently(ref->new_oid.hash, 1))
reject_reason = REF_STATUS_REJECT_NEEDS_FORCE;
-   else if (!ref_newer(ref->new_oid.hash, 
ref->old_oid.hash))
+   else if (!ref_newer(&ref->new_oid, &ref->old_oid))
reject_reason = 
REF_STATUS_REJECT_NONFASTFORWARD;
}
 
@@ -1982,7 +1982,7 @@ static void unmark_and_free(struct commit_list *list, 
unsigned int mark)
}
 }
 
-int ref_newer(const unsigned char *new_sha1, const unsigned char *old_sha1)
+int ref_newer(const struct object_id *new_oid, const struct object_id *old_oid)
 {
struct object *o;
struct commit *old, *new;
@@ -1993,12 +1993,12 @@ int ref_newer(const unsigned char *new_sha1, const 
unsigned char *old_sha1)
 * Both new and old must be commit-ish and new is descendant of
 * old.  Otherwise we require --force.
 */
-   o = deref_tag(parse_object(old_sha1), NULL, 0);
+   o = deref_tag(parse_object(old_oid->hash), NULL, 0);
if (!o || o->type != OBJ_COMMIT)
return 0;
old = (struct commit *) o;
 
-   o = deref_tag(parse_object(new_sha1), NULL, 0);
+   o = deref_tag(parse_object(new_oid->hash), NULL, 0);
if (!o || o->type != OBJ_COMMIT)
return 0;
new = (struct commit *) o;
diff --git a/remote.h b/remote.h
index 163ea5e..4a039ba 100644
--- a/remote.h
+++ b/remote.h
@@ -150,7 +150,7 @@ extern struct ref **get_remote_heads(int in, char *src_buf, 
size_t src_len,
 struct sha1_array *shallow);
 
 int resolve_remote_symref(struct ref *ref, struct ref *list);
-int ref_newer(const unsigned char *new_sha1, const unsigned char *old_sha1);
+int ref_newer(const struct object_id *new_oid, const struct object_id 
*old_oid);
 
 /*
  * Remove and free all but the first of any entries in the input list
-- 
2.4.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 v2 03/10] Convert struct ref to use object_id.

2015-06-13 Thread brian m. carlson
Use struct object_id in three fields in struct ref and convert all the
necessary places that use it.

Signed-off-by: brian m. carlson 
---
 builtin/clone.c| 16 +++---
 builtin/fetch-pack.c   |  4 ++--
 builtin/fetch.c| 50 +--
 builtin/ls-remote.c|  2 +-
 builtin/receive-pack.c |  2 +-
 builtin/remote.c   | 12 +--
 connect.c  |  2 +-
 fetch-pack.c   | 18 
 http-push.c| 46 +++
 http.c |  2 +-
 remote-curl.c  | 10 -
 remote.c   | 58 +-
 remote.h   |  6 +++---
 send-pack.c| 16 +++---
 transport-helper.c | 18 
 transport.c| 32 ++--
 transport.h|  8 +++
 walker.c   |  2 +-
 18 files changed, 152 insertions(+), 152 deletions(-)

diff --git a/builtin/clone.c b/builtin/clone.c
index 00535d0..d164712 100644
--- a/builtin/clone.c
+++ b/builtin/clone.c
@@ -496,7 +496,7 @@ static void write_remote_refs(const struct ref *local_refs)
for (r = local_refs; r; r = r->next) {
if (!r->peer_ref)
continue;
-   add_packed_ref(r->peer_ref->name, r->old_sha1);
+   add_packed_ref(r->peer_ref->name, r->old_oid.hash);
}
 
if (commit_packed_refs())
@@ -511,9 +511,9 @@ static void write_followtags(const struct ref *refs, const 
char *msg)
continue;
if (ends_with(ref->name, "^{}"))
continue;
-   if (!has_sha1_file(ref->old_sha1))
+   if (!has_object_file(&ref->old_oid))
continue;
-   update_ref(msg, ref->name, ref->old_sha1,
+   update_ref(msg, ref->name, ref->old_oid.hash,
   NULL, 0, UPDATE_REFS_DIE_ON_ERR);
}
 }
@@ -533,7 +533,7 @@ static int iterate_ref_map(void *cb_data, unsigned char 
sha1[20])
if (!ref)
return -1;
 
-   hashcpy(sha1, ref->old_sha1);
+   hashcpy(sha1, ref->old_oid.hash);
*rm = ref->next;
return 0;
 }
@@ -582,12 +582,12 @@ static void update_head(const struct ref *our, const 
struct ref *remote,
/* Local default branch link */
create_symref("HEAD", our->name, NULL);
if (!option_bare) {
-   update_ref(msg, "HEAD", our->old_sha1, NULL, 0,
+   update_ref(msg, "HEAD", our->old_oid.hash, NULL, 0,
   UPDATE_REFS_DIE_ON_ERR);
install_branch_config(0, head, option_origin, 
our->name);
}
} else if (our) {
-   struct commit *c = lookup_commit_reference(our->old_sha1);
+   struct commit *c = lookup_commit_reference(our->old_oid.hash);
/* --branch specifies a non-branch (i.e. tags), detach HEAD */
update_ref(msg, "HEAD", c->object.sha1,
   NULL, REF_NODEREF, UPDATE_REFS_DIE_ON_ERR);
@@ -597,7 +597,7 @@ static void update_head(const struct ref *our, const struct 
ref *remote,
 * HEAD points to a branch but we don't know which one.
 * Detach HEAD in all these cases.
 */
-   update_ref(msg, "HEAD", remote->old_sha1,
+   update_ref(msg, "HEAD", remote->old_oid.hash,
   NULL, REF_NODEREF, UPDATE_REFS_DIE_ON_ERR);
}
 }
@@ -948,7 +948,7 @@ int cmd_clone(int argc, const char **argv, const char 
*prefix)
 * remote HEAD check.
 */
for (ref = refs; ref; ref = ref->next)
-   if (is_null_sha1(ref->old_sha1)) {
+   if (is_null_oid(&ref->old_oid)) {
complete_refs_before_fetch = 0;
break;
}
diff --git a/builtin/fetch-pack.c b/builtin/fetch-pack.c
index 4a6b340..19215b3 100644
--- a/builtin/fetch-pack.c
+++ b/builtin/fetch-pack.c
@@ -17,7 +17,7 @@ static void add_sought_entry_mem(struct ref ***sought, int 
*nr, int *alloc,
unsigned char sha1[20];
 
if (namelen > 41 && name[40] == ' ' && !get_sha1_hex(name, sha1)) {
-   hashcpy(ref->old_sha1, sha1);
+   hashcpy(ref->old_oid.hash, sha1);
name += 41;
namelen -= 41;
}
@@ -210,7 +210,7 @@ int cmd_fetch_pack(int argc, const char **argv, const char 
*prefix)
 
while (ref) {
printf("%s %s\n",
-  sha1_to_hex(ref->old_sha1), ref->name);
+  oid_to_hex(&ref->old_oid), ref->name);
ref = ref->next;
}
 
diff --git a/builtin/fetch.c b/builtin/fetch.c
index 8d5b2db

[PATCH v2 02/10] sha1_file: introduce has_object_file helper.

2015-06-13 Thread brian m. carlson
Add has_object_file, which is a wrapper around has_sha1_file, but for
struct object_id.

Signed-off-by: brian m. carlson 
---
 cache.h | 3 +++
 sha1_file.c | 5 +
 2 files changed, 8 insertions(+)

diff --git a/cache.h b/cache.h
index 571c98f..fa1f067 100644
--- a/cache.h
+++ b/cache.h
@@ -946,6 +946,9 @@ extern int has_sha1_pack(const unsigned char *sha1);
  */
 extern int has_sha1_file(const unsigned char *sha1);
 
+/* Same as the above, except for struct object_id. */
+extern int has_object_file(const struct object_id *oid);
+
 /*
  * Return true iff an alternate object database has a loose object
  * with the specified name.  This function does not respect replace
diff --git a/sha1_file.c b/sha1_file.c
index 5038475..2bad0cd 100644
--- a/sha1_file.c
+++ b/sha1_file.c
@@ -3180,6 +3180,11 @@ int has_sha1_file(const unsigned char *sha1)
return find_pack_entry(sha1, &e);
 }
 
+int has_object_file(const struct object_id *oid)
+{
+   return has_sha1_file(oid->hash);
+}
+
 static void check_tree(const void *buf, size_t size)
 {
struct tree_desc desc;
-- 
2.4.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 v2 10/10] remote: convert functions to struct object_id

2015-06-13 Thread brian m. carlson
Convert several unsigned char arrays to use struct object_id instead,
and change hard-coded 40-based constants to use GIT_SHA1_HEXSZ as well.

Signed-off-by: brian m. carlson 
---
 remote.c | 64 
 1 file changed, 32 insertions(+), 32 deletions(-)

diff --git a/remote.c b/remote.c
index c72d796..92dc8d6 100644
--- a/remote.c
+++ b/remote.c
@@ -492,7 +492,7 @@ static void alias_all_urls(void)
 static void read_config(void)
 {
static int loaded;
-   unsigned char sha1[20];
+   struct object_id oid;
const char *head_ref;
int flag;
 
@@ -501,7 +501,7 @@ static void read_config(void)
loaded = 1;
 
current_branch = NULL;
-   head_ref = resolve_ref_unsafe("HEAD", 0, sha1, &flag);
+   head_ref = resolve_ref_unsafe("HEAD", 0, oid.hash, &flag);
if (head_ref && (flag & REF_ISSYMREF) &&
skip_prefix(head_ref, "refs/heads/", &head_ref)) {
current_branch = make_branch(head_ref, 0);
@@ -580,12 +580,12 @@ static struct refspec *parse_refspec_internal(int 
nr_refspec, const char **refsp
flags = REFNAME_ALLOW_ONELEVEL | (is_glob ? 
REFNAME_REFSPEC_PATTERN : 0);
 
if (fetch) {
-   unsigned char unused[40];
+   struct object_id unused;
 
/* LHS */
if (!*rs[i].src)
; /* empty is ok; it means "HEAD" */
-   else if (llen == 40 && !get_sha1_hex(rs[i].src, unused))
+   else if (llen == GIT_SHA1_HEXSZ && 
!get_oid_hex(rs[i].src, &unused))
rs[i].exact_sha1 = 1; /* ok */
else if (!check_refname_format(rs[i].src, flags))
; /* valid looking ref is ok */
@@ -1118,7 +1118,7 @@ static struct ref *alloc_delete_ref(void)
 static int try_explicit_object_name(const char *name,
struct ref **match)
 {
-   unsigned char sha1[20];
+   struct object_id oid;
 
if (!*name) {
if (match)
@@ -1126,12 +1126,12 @@ static int try_explicit_object_name(const char *name,
return 0;
}
 
-   if (get_sha1(name, sha1))
+   if (get_sha1(name, oid.hash))
return -1;
 
if (match) {
*match = alloc_ref(name);
-   hashcpy((*match)->new_oid.hash, sha1);
+   oidcpy(&(*match)->new_oid, &oid);
}
return 0;
 }
@@ -1146,10 +1146,10 @@ static struct ref *make_linked_ref(const char *name, 
struct ref ***tail)
 static char *guess_ref(const char *name, struct ref *peer)
 {
struct strbuf buf = STRBUF_INIT;
-   unsigned char sha1[20];
+   struct object_id oid;
 
const char *r = resolve_ref_unsafe(peer->name, RESOLVE_REF_READING,
-  sha1, NULL);
+  oid.hash, NULL);
if (!r)
return NULL;
 
@@ -1207,12 +1207,12 @@ static int match_explicit(struct ref *src, struct ref 
*dst,
return -1;
 
if (!dst_value) {
-   unsigned char sha1[20];
+   struct object_id oid;
int flag;
 
dst_value = resolve_ref_unsafe(matched_src->name,
   RESOLVE_REF_READING,
-  sha1, &flag);
+  oid.hash, &flag);
if (!dst_value ||
((flag & REF_ISSYMREF) &&
 !starts_with(dst_value, "refs/heads/")))
@@ -1328,13 +1328,13 @@ struct tips {
int nr, alloc;
 };
 
-static void add_to_tips(struct tips *tips, const unsigned char *sha1)
+static void add_to_tips(struct tips *tips, const struct object_id *oid)
 {
struct commit *commit;
 
-   if (is_null_sha1(sha1))
+   if (is_null_oid(oid))
return;
-   commit = lookup_commit_reference_gently(sha1, 1);
+   commit = lookup_commit_reference_gently(oid->hash, 1);
if (!commit || (commit->object.flags & TMP_MARK))
return;
commit->object.flags |= TMP_MARK;
@@ -1358,9 +1358,9 @@ static void add_missing_tags(struct ref *src, struct ref 
**dst, struct ref ***ds
for (ref = *dst; ref; ref = ref->next) {
if (ref->peer_ref &&
!is_null_oid(&ref->peer_ref->new_oid))
-   add_to_tips(&sent_tips, ref->peer_ref->new_oid.hash);
+   add_to_tips(&sent_tips, &ref->peer_ref->new_oid);
else
-   add_to_tips(&sent_tips, ref->old_oid.hash);
+   add_to_tips(&sent_tips, &ref->old_oid);
if (starts_with(ref->name, "refs/tags/"))
string_list_append(&dst_tag, ref->name);
  

[PATCH v2 07/10] push_refs_with_export: convert to struct object_id

2015-06-13 Thread brian m. carlson
Signed-off-by: brian m. carlson 
---
 transport-helper.c | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/transport-helper.c b/transport-helper.c
index 4ca3e80..1f28b82 100644
--- a/transport-helper.c
+++ b/transport-helper.c
@@ -877,13 +877,13 @@ static int push_refs_with_export(struct transport 
*transport,
 
for (ref = remote_refs; ref; ref = ref->next) {
char *private;
-   unsigned char sha1[20];
+   struct object_id oid;
 
private = apply_refspecs(data->refspecs, data->refspec_nr, 
ref->name);
-   if (private && !get_sha1(private, sha1)) {
+   if (private && !get_sha1(private, oid.hash)) {
strbuf_addf(&buf, "^%s", private);
string_list_append(&revlist_args, strbuf_detach(&buf, 
NULL));
-   hashcpy(ref->old_oid.hash, sha1);
+   oidcpy(&ref->old_oid, &oid);
}
free(private);
 
@@ -897,7 +897,7 @@ static int push_refs_with_export(struct transport 
*transport,
name = resolve_ref_unsafe(
 ref->peer_ref->name,
 RESOLVE_REF_READING,
-sha1, &flag);
+oid.hash, &flag);
if (!name || !(flag & REF_ISSYMREF))
name = ref->peer_ref->name;
 
-- 
2.4.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 v2 06/10] get_remote_heads: convert to struct object_id

2015-06-13 Thread brian m. carlson
Replace an unsigned char array with struct object_id and express several
hard-coded constants in terms of GIT_SHA1_HEXSZ.

Signed-off-by: brian m. carlson 
---
 connect.c | 22 --
 1 file changed, 12 insertions(+), 10 deletions(-)

diff --git a/connect.c b/connect.c
index f8b10eb..7f005a7 100644
--- a/connect.c
+++ b/connect.c
@@ -119,7 +119,7 @@ struct ref **get_remote_heads(int in, char *src_buf, size_t 
src_len,
*list = NULL;
for (;;) {
struct ref *ref;
-   unsigned char old_sha1[20];
+   struct object_id old_oid;
char *name;
int len, name_len;
char *buffer = packet_buffer;
@@ -138,34 +138,36 @@ struct ref **get_remote_heads(int in, char *src_buf, 
size_t src_len,
if (len > 4 && skip_prefix(buffer, "ERR ", &arg))
die("remote error: %s", arg);
 
-   if (len == 48 && skip_prefix(buffer, "shallow ", &arg)) {
-   if (get_sha1_hex(arg, old_sha1))
+   if (len == GIT_SHA1_HEXSZ + strlen("shallow ") &&
+   skip_prefix(buffer, "shallow ", &arg)) {
+   if (get_oid_hex(arg, &old_oid))
die("protocol error: expected shallow sha-1, 
got '%s'", arg);
if (!shallow_points)
die("repository on the other end cannot be 
shallow");
-   sha1_array_append(shallow_points, old_sha1);
+   sha1_array_append(shallow_points, old_oid.hash);
continue;
}
 
-   if (len < 42 || get_sha1_hex(buffer, old_sha1) || buffer[40] != 
' ')
+   if (len < GIT_SHA1_HEXSZ + 2 || get_oid_hex(buffer, &old_oid) ||
+   buffer[GIT_SHA1_HEXSZ] != ' ')
die("protocol error: expected sha/ref, got '%s'", 
buffer);
-   name = buffer + 41;
+   name = buffer + GIT_SHA1_HEXSZ + 1;
 
name_len = strlen(name);
-   if (len != name_len + 41) {
+   if (len != name_len + GIT_SHA1_HEXSZ + 1) {
free(server_capabilities);
server_capabilities = xstrdup(name + name_len + 1);
}
 
if (extra_have && !strcmp(name, ".have")) {
-   sha1_array_append(extra_have, old_sha1);
+   sha1_array_append(extra_have, old_oid.hash);
continue;
}
 
if (!check_ref(name, flags))
continue;
-   ref = alloc_ref(buffer + 41);
-   hashcpy(ref->old_oid.hash, old_sha1);
+   ref = alloc_ref(buffer + GIT_SHA1_HEXSZ + 1);
+   oidcpy(&ref->old_oid, &old_oid);
*list = ref;
list = &ref->next;
got_at_least_one_head = 1;
-- 
2.4.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 v2 04/10] add_sought_entry_mem: convert to struct object_id

2015-06-13 Thread brian m. carlson
Convert this function to use struct object_id.  Express several
hardcoded constants in terms of GIT_SHA1_HEXSZ.

Signed-off-by: brian m. carlson 
---
 builtin/fetch-pack.c | 12 +++-
 1 file changed, 7 insertions(+), 5 deletions(-)

diff --git a/builtin/fetch-pack.c b/builtin/fetch-pack.c
index 19215b3..cf3019e 100644
--- a/builtin/fetch-pack.c
+++ b/builtin/fetch-pack.c
@@ -14,12 +14,14 @@ static void add_sought_entry_mem(struct ref ***sought, int 
*nr, int *alloc,
 const char *name, int namelen)
 {
struct ref *ref = xcalloc(1, sizeof(*ref) + namelen + 1);
-   unsigned char sha1[20];
+   struct object_id oid;
+   const int chunksz = GIT_SHA1_HEXSZ + 1;
 
-   if (namelen > 41 && name[40] == ' ' && !get_sha1_hex(name, sha1)) {
-   hashcpy(ref->old_oid.hash, sha1);
-   name += 41;
-   namelen -= 41;
+   if (namelen > chunksz && name[chunksz - 1] == ' ' &&
+   !get_oid_hex(name, &oid)) {
+   oidcpy(&ref->old_oid, &oid);
+   name += chunksz;
+   namelen -= chunksz;
}
 
memcpy(ref->name, name, namelen);
-- 
2.4.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


[GSOC] Week 2: Unification of tag -l, branch -l and for-each-ref

2015-06-13 Thread karthik nayak
Hello All,

As part of GSoC I'm working on the Unification of 'for-each-ref', 'tag -l'
and 'branch -l'. I will update the list on my weekly progress in an effort
to keep everyone updated.

Current Progress:
Currently I have two patches for review on the mailing list.

1. [PATCH v8 0/11] Create ref-filter from for-each-ref
(http://article.gmane.org/gmane.comp.version-control.git/271563)
This is basically related to the movement of code from for-each-ref to
ref-filter. ref-filter would act as a base for tag -l and branch -l. They can
eventually use the ref-filter APIs to implement the --format and --sort options
provided by ref-filter.

2. [PATCH v2 00/11] add options to for-each-ref
(http://article.gmane.org/gmane.comp.version-control.git/271575)
This relates to the addition of options like '--points-at',
'--merged', '--no-merged'
and '--contains' options to ref-filter and making use of these options
in for-each-ref
and implementing tests for the same.

Work in progress:
You can follow my current progress on Github:
https://github.com/KarthikNayak/git
Currently working on bringing tag.c on board and making it use the
ref-filter APIs and implement the various options provided by
ref-filter.
This might require an option of having ref-filter sort based on
version no when listing refnames.

Whats next:
After getting tag.c to work with ref-filter APIs. Start porting branch
-l to use ref-filter
APIs too.





-- 
Regards,
Karthik Nayak
--
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] Makefile / racy-git.txt: clarify USE_NSEC prerequisites

2015-06-13 Thread Karsten Blees
Signed-off-by: Karsten Blees 
---
Enabling nanosecond file times was recently discussed on the libgit2 project, so
I thought its time to fix the nanosecond issue on Linux. Don't know yet if the
patch will be accepted (and in which kernel version).

Considering that nanosecond file times are still broken for some file systems, 
it
may be desirable to make this a config option in addition to the compile-time
setting? I.e. only use sub-second file times for up-to-date checks if the config
option is enabled, so that it can be turned off on file systems with flaky
timestamps.

 Documentation/technical/racy-git.txt | 8 ++--
 Makefile | 9 +
 2 files changed, 11 insertions(+), 6 deletions(-)

diff --git a/Documentation/technical/racy-git.txt 
b/Documentation/technical/racy-git.txt
index 242a044..89ca173 100644
--- a/Documentation/technical/racy-git.txt
+++ b/Documentation/technical/racy-git.txt
@@ -42,12 +42,16 @@ compared, but this is not enabled by default because this 
member
 is not stable on network filesystems.  With `USE_NSEC`
 compile-time option, `st_mtim.tv_nsec` and `st_ctim.tv_nsec`
 members are also compared, but this is not enabled by default
-because in-core timestamps can have finer granularity than
+because on Linux, in-core timestamps can have finer granularity than
 on-disk timestamps, resulting in meaningless changes when an
 inode is evicted from the inode cache.  See commit 8ce13b0
 of git://git.kernel.org/pub/scm/linux/kernel/git/tglx/history.git
 ([PATCH] Sync in core time granularity with filesystems,
-2005-01-04).
+2005-01-04). This patch is included in kernel 2.6.11 and newer, but
+only fixes the issue for file systems with exactly 1 ns or 1 s
+resolution. Other file systems are still broken in current Linux
+kernels (e.g. CEPH, CIFS, NTFS, UDF), see
+https://lkml.org/lkml/2015/6/9/714
 
 Racy Git
 
diff --git a/Makefile b/Makefile
index 54ec511..46d181a 100644
--- a/Makefile
+++ b/Makefile
@@ -217,10 +217,11 @@ all::
 # as the compiler can crash (http://gcc.gnu.org/bugzilla/show_bug.cgi?id=49299)
 #
 # Define USE_NSEC below if you want git to care about sub-second file mtimes
-# and ctimes. Note that you need recent glibc (at least 2.2.4) for this, and
-# it will BREAK YOUR LOCAL DIFFS! show-diff and anything using it will likely
-# randomly break unless your underlying filesystem supports those sub-second
-# times (my ext3 doesn't).
+# and ctimes. Note that you need recent glibc (at least 2.2.4) for this. On
+# Linux, kernel 2.6.11 or newer is required for reliable sub-second file times
+# on file systems with exactly 1 ns or 1 s resolution. If you intend to use Git
+# on other file systems (e.g. CEPH, CIFS, NTFS, UDF), don't enable USE_NSEC. 
See
+# Documentation/technical/racy-git.txt for details.
 #
 # Define USE_ST_TIMESPEC if your "struct stat" uses "st_ctimespec" instead of
 # "st_ctim"
-- 
2.4.3.windows.1.1.g87477f9

--
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/i18n.txt: clarify character encoding support

2015-06-13 Thread Karsten Blees
As a "distributed" VCS, git should better define the encodings of its core
textual data structures, in particular those that are part of the network
protocol.

That git is encoding agnostic is only really true for blob objects. E.g.
the 'non-NUL bytes' requirement of tree and commit objects excludes
UTF-16/32, and the special meaning of '/' in the index file as well as
space and linefeed in commit objects eliminates EBCDIC and other non-ASCII
encodings.

Git expects bytes < 0x80 to be pure ASCII, thus CJK encodings that partly
overlap with the ASCII range are problematic as well. E.g. fmt_ident()
removes trailing 0x5C from user names on the assumption that it is ASCII
'\'. However, there are over 200 GBK double byte codes that end in 0x5C.

UTF-8 as default encoding on Linux and respective path translations in the
Mac and Windows versions have established UTF-8 NFC as de-facto standard
for path names.

Update the documentation in i18n.txt to reflect the current status-quo.

Signed-off-by: Karsten Blees 
---
 Documentation/i18n.txt | 30 --
 1 file changed, 20 insertions(+), 10 deletions(-)

diff --git a/Documentation/i18n.txt b/Documentation/i18n.txt
index e9a1d5d..e5f6233 100644
--- a/Documentation/i18n.txt
+++ b/Documentation/i18n.txt
@@ -1,18 +1,28 @@
-At the core level, Git is character encoding agnostic.
-
- - The pathnames recorded in the index and in the tree objects
-   are treated as uninterpreted sequences of non-NUL bytes.
-   What readdir(2) returns are what are recorded and compared
-   with the data Git keeps track of, which in turn are expected
-   to be what lstat(2) and creat(2) accepts.  There is no such
-   thing as pathname encoding translation.
+Git is to some extent character encoding agnostic.
 
  - The contents of the blob objects are uninterpreted sequences
of bytes.  There is no encoding translation at the core
level.
 
- - The commit log messages are uninterpreted sequences of non-NUL
-   bytes.
+ - Pathnames are encoded in UTF-8 normalization form C. This
+   applies to tree objects, the index file, ref names and
+   config files (`.git/config` (see linkgit:git-config[1]),
+   linkgit:gitignore[5], linkgit:gitattributes[5] and
+   linkgit:gitmodules[5]).
+   The Mac and Windows versions automatically translate pathnames
+   to and from UTF-8 NFC in their readdir(2), lstat(2), creat(2)
+   etc. APIs. However, there is no such translation on other
+   platforms. If file system APIs don't use UTF-8 (which may be
+   file system specific), it is recommended to stick to pure
+   ASCII file names. While Git technically supports other
+   extended ASCII encodings at the core level, such repositories
+   will not be portable.
+
+ - Commit log messages are typically encoded in UTF-8, but other
+   extended ASCII encodings are also supported. This includes
+   ISO-8859-x, CP125x and many others, but _not_ UTF-16/32,
+   EBCDIC and CJK multi-byte encodings (GBK, Shift-JIS, Big5,
+   EUC-x, CP9xx etc.).
 
 Although we encourage that the commit log messages are encoded
 in UTF-8, both the core and Git Porcelain are designed not to
-- 
2.4.1.windows.1

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


[PATCH (resend)] git-gui: make gc warning threshold match 'git gc --auto'

2015-06-13 Thread Karsten Blees
Date: Wed, 6 Aug 2014 20:43:46 +0200

The number of loose objects at which git-gui shows a gc warning has
historically been hardcoded to ~2000, or ~200 on Windows. The warning can
only be disabled completely via gui.gcwarning=false.

Especially on Windows, the hardcoded threshold is so ridiculously low that
git-gui often complains even immediately after gc (due to loose objects
only referenced by the reflog).

'git gc --auto' uses a much bigger threshold to check if gc is necessary.
Additionally, the value can be configured via gc.auto (default 6700).
There's no special case for Windows.

Change git-gui so that it only warns if 'git gc --auto' would also do an
automatic gc, i.e.:
 - calculate the threshold from the gc.auto setting (default 6700,
   disabled if <= 0)
 - check directory .git/objects/17

We still check four directories (14-17) if gc.auto is very small, to get a
better estimate.

Signed-off-by: Karsten Blees 
---
 git-gui/lib/database.tcl | 17 -
 1 file changed, 12 insertions(+), 5 deletions(-)

diff --git a/git-gui/lib/database.tcl b/git-gui/lib/database.tcl
index 1f187ed..212b195 100644
--- a/git-gui/lib/database.tcl
+++ b/git-gui/lib/database.tcl
@@ -89,19 +89,26 @@ proc do_fsck_objects {} {
 }
 
 proc hint_gc {} {
+   global repo_config
+   set auto_gc $repo_config(gc.auto)
+   if {$auto_gc eq {}} {
+   set auto_gc 6700
+   } elseif {$auto_gc <= 0} {
+   return
+   }
+
set ndirs 1
-   set limit 8
-   if {[is_Windows]} {
+   set limit [expr {($auto_gc + 255) / 256}]
+   if {$limit < 4} {
set ndirs 4
-   set limit 1
}
 
set count [llength [glob \
-nocomplain \
-- \
-   [gitdir objects 4\[0-[expr {$ndirs-1}]\]/*]]]
+   [gitdir objects 1\[[expr {8-$ndirs}]-7\]/*]]]
 
-   if {$count >= $limit * $ndirs} {
+   if {$count > $limit * $ndirs} {
set objects_current [expr {$count * 256/$ndirs}]
if {[ask_popup \
[mc "This repository currently has approximately %i 
loose objects.
-- 
2.4.1.windows.1

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


[PATCH v2 07/11] for-each-ref: add '--merged' and '--no-merged' options

2015-06-13 Thread Karthik Nayak
Add the '--merged' and '--no-merged' options provided by 'ref-filter'.
The '--merged' option lets the user to only list refs merged into the
named commit. The '--no-merged' option lets the user to only list refs
not merged into the named commit.

Add documentation and tests for the same.

Based-on-patch-by: Jeff King 
Mentored-by: Christian Couder 
Mentored-by: Matthieu Moy 
Signed-off-by: Karthik Nayak 
---
 Documentation/git-for-each-ref.txt | 10 +-
 builtin/for-each-ref.c |  3 +++
 t/t6301-for-each-ref-filter.sh | 21 +
 3 files changed, 33 insertions(+), 1 deletion(-)

diff --git a/Documentation/git-for-each-ref.txt 
b/Documentation/git-for-each-ref.txt
index 0524ac4..d61a756 100644
--- a/Documentation/git-for-each-ref.txt
+++ b/Documentation/git-for-each-ref.txt
@@ -10,7 +10,7 @@ SYNOPSIS
 [verse]
 'git for-each-ref' [--count=] [--shell|--perl|--python|--tcl]
   [(--sort=)...] [--format=] [...]
-  [--points-at ]
+  [--points-at ] [(--merged | --no-merged) ]
 
 DESCRIPTION
 ---
@@ -66,6 +66,14 @@ OPTIONS
 --points-at ::
Only list refs of the given object.
 
+--merged []::
+   Only list refs whose tips are reachable from the
+   specified commit (HEAD if not specified).
+
+--no-merged []::
+   Only list refs whose tips are not reachable from the
+   specified commit (HEAD if not specified).
+
 FIELD NAMES
 ---
 
diff --git a/builtin/for-each-ref.c b/builtin/for-each-ref.c
index 2dee149..00913f4 100644
--- a/builtin/for-each-ref.c
+++ b/builtin/for-each-ref.c
@@ -8,6 +8,7 @@
 static char const * const for_each_ref_usage[] = {
N_("git for-each-ref [] []"),
N_("git for-each-ref [--points-at ]"),
+   N_("git for-each-ref [(--merged | --no-merged) ]"),
NULL
 };
 
@@ -38,6 +39,8 @@ int cmd_for_each_ref(int argc, const char **argv, const char 
*prefix)
OPT_CALLBACK(0, "points-at", &filter.points_at,
 N_("object"), N_("print only refs of the object"),
 parse_opt_object_name),
+   OPT_MERGED(&filter, N_("print only refs that are merged")),
+   OPT_NO_MERGED(&filter, N_("print only refs that are not 
merged")),
OPT_END(),
};
 
diff --git a/t/t6301-for-each-ref-filter.sh b/t/t6301-for-each-ref-filter.sh
index 3a1c3f6..3ed97bd 100644
--- a/t/t6301-for-each-ref-filter.sh
+++ b/t/t6301-for-each-ref-filter.sh
@@ -42,4 +42,25 @@ test_expect_success 'filtering with --points-at' '
test_cmp expect actual
 '
 
+test_expect_success 'filtering with --merged' '
+   cat >expect <<-\EOF &&
+   refs/heads/master
+   refs/odd/spot
+   refs/tags/one
+   refs/tags/three
+   refs/tags/two
+   EOF
+   git for-each-ref --format="%(refname)" --merged=master >actual &&
+   test_cmp expect actual
+'
+
+test_expect_success 'filtering with --no-merged' '
+   cat >expect <<-\EOF &&
+   refs/heads/side
+   refs/tags/four
+   EOF
+   git for-each-ref --format="%(refname)" --no-merged=master >actual &&
+   test_cmp expect actual
+'
+
 test_done
-- 
2.4.3.435.g2403634.dirty

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


[PATCH v2 11/11] for-each-ref: add '--contains' option

2015-06-13 Thread Karthik Nayak
Add the '--contains' option provided by 'ref-filter'. The '--contains'
option lists only refs which are contain the mentioned commit (HEAD if
no commit is explicitly given).

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 |  5 +
 builtin/for-each-ref.c |  2 ++
 t/t6301-for-each-ref-filter.sh | 13 +
 3 files changed, 20 insertions(+)

diff --git a/Documentation/git-for-each-ref.txt 
b/Documentation/git-for-each-ref.txt
index d61a756..7a949f3 100644
--- a/Documentation/git-for-each-ref.txt
+++ b/Documentation/git-for-each-ref.txt
@@ -11,6 +11,7 @@ SYNOPSIS
 'git for-each-ref' [--count=] [--shell|--perl|--python|--tcl]
   [(--sort=)...] [--format=] [...]
   [--points-at ] [(--merged | --no-merged) ]
+  [--contains ]
 
 DESCRIPTION
 ---
@@ -74,6 +75,10 @@ OPTIONS
Only list refs whose tips are not reachable from the
specified commit (HEAD if not specified).
 
+--contains []::
+   Only list tags which contain the specified commit (HEAD if not
+   specified).
+
 FIELD NAMES
 ---
 
diff --git a/builtin/for-each-ref.c b/builtin/for-each-ref.c
index 00913f4..8ccbb1c 100644
--- a/builtin/for-each-ref.c
+++ b/builtin/for-each-ref.c
@@ -9,6 +9,7 @@ static char const * const for_each_ref_usage[] = {
N_("git for-each-ref [] []"),
N_("git for-each-ref [--points-at ]"),
N_("git for-each-ref [(--merged | --no-merged) ]"),
+   N_("git for-each-ref [--contains ]"),
NULL
 };
 
@@ -41,6 +42,7 @@ int cmd_for_each_ref(int argc, const char **argv, const char 
*prefix)
 parse_opt_object_name),
OPT_MERGED(&filter, N_("print only refs that are merged")),
OPT_NO_MERGED(&filter, N_("print only refs that are not 
merged")),
+   OPT_CONTAINS(&filter.with_commit, N_("print only refs which 
contain the commit")),
OPT_END(),
};
 
diff --git a/t/t6301-for-each-ref-filter.sh b/t/t6301-for-each-ref-filter.sh
index 3ed97bd..17cf7b0 100644
--- a/t/t6301-for-each-ref-filter.sh
+++ b/t/t6301-for-each-ref-filter.sh
@@ -63,4 +63,17 @@ test_expect_success 'filtering with --no-merged' '
test_cmp expect actual
 '
 
+test_expect_success 'filtering with --contains' '
+   cat >expect <<-\EOF &&
+   refs/heads/master
+   refs/heads/side
+   refs/odd/spot
+   refs/tags/four
+   refs/tags/three
+   refs/tags/two
+   EOF
+   git for-each-ref --format="%(refname)" --contains=two >actual &&
+   test_cmp expect actual
+'
+
 test_done
-- 
2.4.3.435.g2403634.dirty

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


[PATCH v2 08/11] parse-option: rename parse_opt_with_commit()

2015-06-13 Thread Karthik Nayak
Rename parse_opt_with_commit() to parse_opt_commit_object_name()
to show that it can be used to obtain a list of commits and is
not constricted to usage of '--contains' option.

Mentored-by: Christian Couder 
Mentored-by: Matthieu Moy 
Signed-off-by: Karthik Nayak 
---
 builtin/branch.c   | 4 ++--
 builtin/tag.c  | 4 ++--
 parse-options-cb.c | 2 +-
 parse-options.h| 2 +-
 4 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/builtin/branch.c b/builtin/branch.c
index ddd90e6..ddd728e 100644
--- a/builtin/branch.c
+++ b/builtin/branch.c
@@ -828,13 +828,13 @@ int cmd_branch(int argc, const char **argv, const char 
*prefix)
OPTION_CALLBACK, 0, "contains", &with_commit, 
N_("commit"),
N_("print only branches that contain the commit"),
PARSE_OPT_LASTARG_DEFAULT,
-   parse_opt_with_commit, (intptr_t)"HEAD",
+   parse_opt_commit_object_name, (intptr_t)"HEAD",
},
{
OPTION_CALLBACK, 0, "with", &with_commit, N_("commit"),
N_("print only branches that contain the commit"),
PARSE_OPT_HIDDEN | PARSE_OPT_LASTARG_DEFAULT,
-   parse_opt_with_commit, (intptr_t) "HEAD",
+   parse_opt_commit_object_name, (intptr_t) "HEAD",
},
OPT__ABBREV(&abbrev),
 
diff --git a/builtin/tag.c b/builtin/tag.c
index 280981f..2d6610a 100644
--- a/builtin/tag.c
+++ b/builtin/tag.c
@@ -603,13 +603,13 @@ int cmd_tag(int argc, const char **argv, const char 
*prefix)
OPTION_CALLBACK, 0, "contains", &with_commit, 
N_("commit"),
N_("print only tags that contain the commit"),
PARSE_OPT_LASTARG_DEFAULT,
-   parse_opt_with_commit, (intptr_t)"HEAD",
+   parse_opt_commit_object_name, (intptr_t)"HEAD",
},
{
OPTION_CALLBACK, 0, "with", &with_commit, N_("commit"),
N_("print only tags that contain the commit"),
PARSE_OPT_HIDDEN | PARSE_OPT_LASTARG_DEFAULT,
-   parse_opt_with_commit, (intptr_t)"HEAD",
+   parse_opt_commit_object_name, (intptr_t)"HEAD",
},
{
OPTION_CALLBACK, 0, "points-at", &points_at, 
N_("object"),
diff --git a/parse-options-cb.c b/parse-options-cb.c
index de75411..8bec5e4 100644
--- a/parse-options-cb.c
+++ b/parse-options-cb.c
@@ -77,7 +77,7 @@ int parse_opt_verbosity_cb(const struct option *opt, const 
char *arg,
return 0;
 }
 
-int parse_opt_with_commit(const struct option *opt, const char *arg, int unset)
+int parse_opt_commit_object_name(const struct option *opt, const char *arg, 
int unset)
 {
unsigned char sha1[20];
struct commit *commit;
diff --git a/parse-options.h b/parse-options.h
index 36c71fe..8542d9c 100644
--- a/parse-options.h
+++ b/parse-options.h
@@ -221,7 +221,7 @@ extern int parse_opt_expiry_date_cb(const struct option *, 
const char *, int);
 extern int parse_opt_color_flag_cb(const struct option *, const char *, int);
 extern int parse_opt_verbosity_cb(const struct option *, const char *, int);
 extern int parse_opt_object_name(const struct option *, const char *, int);
-extern int parse_opt_with_commit(const struct option *, const char *, int);
+extern int parse_opt_commit_object_name(const struct option *, const char *, 
int);
 extern int parse_opt_tertiary(const struct option *, const char *, int);
 extern int parse_opt_string_list(const struct option *, const char *, int);
 extern int parse_opt_noop_cb(const struct option *, const char *, int);
-- 
2.4.3.435.g2403634.dirty

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


[PATCH v2 10/11] ref-filter: implement '--contains' option

2015-06-13 Thread Karthik Nayak
'tag -l' and 'branch -l' have two different ways of finding
out if a certain ref contains a commit. Implement both these
methods in ref-filter and give the caller of ref-filter API
the option to pick which implementation to be used.

'branch -l' uses 'is_descendant_of()' from commit.c which is
left as the default implementation to be used.

'tag -l' uses a more specific algorithm since ffc4b80. This
implementation is used whenever the 'with_commit_tag_algo' bit
is set in 'struct ref_filter'.

Mentored-by: Christian Couder 
Mentored-by: Matthieu Moy 
Signed-off-by: Karthik Nayak 
---
 ref-filter.c | 112 ++-
 ref-filter.h |   3 ++
 2 files changed, 114 insertions(+), 1 deletion(-)

diff --git a/ref-filter.c b/ref-filter.c
index 06328eb..40eb90e 100644
--- a/ref-filter.c
+++ b/ref-filter.c
@@ -818,6 +818,113 @@ static void get_ref_atom_value(struct ref_array_item 
*ref, int atom, struct atom
*v = &ref->value[atom];
 }
 
+enum contains_result {
+   CONTAINS_UNKNOWN = -1,
+   CONTAINS_NO = 0,
+   CONTAINS_YES = 1
+};
+
+/*
+ * Mimicking the real stack, this stack lives on the heap, avoiding stack
+ * overflows.
+ *
+ * At each recursion step, the stack items points to the commits whose
+ * ancestors are to be inspected.
+ */
+struct contains_stack {
+   int nr, alloc;
+   struct contains_stack_entry {
+   struct commit *commit;
+   struct commit_list *parents;
+   } *contains_stack;
+};
+
+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;
+}
+
+/*
+ * 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_result contains_test(struct commit *candidate,
+   const struct commit_list *want)
+{
+   /* was it previously marked as containing a want commit? */
+   if (candidate->object.flags & TMP_MARK)
+   return 1;
+   /* or marked as not possibly containing a want commit? */
+   if (candidate->object.flags & UNINTERESTING)
+   return 0;
+   /* or are we it? */
+   if (in_commit_list(want, candidate)) {
+   candidate->object.flags |= TMP_MARK;
+   return 1;
+   }
+
+   if (parse_commit(candidate) < 0)
+   return 0;
+
+   return -1;
+}
+
+static void push_to_contains_stack(struct commit *candidate, struct 
contains_stack *contains_stack)
+{
+   ALLOC_GROW(contains_stack->contains_stack, contains_stack->nr + 1, 
contains_stack->alloc);
+   contains_stack->contains_stack[contains_stack->nr].commit = candidate;
+   contains_stack->contains_stack[contains_stack->nr++].parents = 
candidate->parents;
+}
+
+static enum contains_result contains_tag_algo(struct commit *candidate,
+   const struct commit_list *want)
+{
+   struct contains_stack contains_stack = { 0, 0, NULL };
+   int result = contains_test(candidate, want);
+
+   if (result != CONTAINS_UNKNOWN)
+   return result;
+
+   push_to_contains_stack(candidate, &contains_stack);
+   while (contains_stack.nr) {
+   struct contains_stack_entry *entry = 
&contains_stack.contains_stack[contains_stack.nr - 1];
+   struct commit *commit = entry->commit;
+   struct commit_list *parents = entry->parents;
+
+   if (!parents) {
+   commit->object.flags |= UNINTERESTING;
+   contains_stack.nr--;
+   }
+   /*
+* If we just popped the stack, parents->item has been marked,
+* therefore contains_test will return a meaningful 0 or 1.
+*/
+   else switch (contains_test(parents->item, want)) {
+   case CONTAINS_YES:
+   commit->object.flags |= TMP_MARK;
+   contains_stack.nr--;
+   break;
+   case CONTAINS_NO:
+   entry->parents = parents->next;
+   break;
+   case CONTAINS_UNKNOWN:
+   push_to_contains_stack(parents->item, &contains_stack);
+   break;
+   }
+   }
+   free(contains_stack.contains_stack);
+   return contains_test(candidate, want);
+}
+
+static int commit_contains(struct ref_filter *filter, struct commit *commit)
+{
+   if (filter->with_commit_tag_algo)
+   return contains_tag_algo(commit, filter->with_commit);
+   return is_descendant_of(commit, filter->with_commit);
+}
 /*
  * Return 1 if the refname matches one of the patterns, otherwise 0.
  * A pattern can be path prefix (e.g. a refname "refs/hea

[PATCH v2 09/11] parse-options.h: add macros for '--contains' option

2015-06-13 Thread Karthik Nayak
Add a macro for using the '--contains' option in parse-options.h
also include an optional '--with' option macro which performs the
same action as '--contains'.

Make tag.c use this new macro

Mentored-by: Christian Couder 
Mentored-by: Matthieu Moy 
Signed-off-by: Karthik Nayak 
---
 builtin/tag.c   | 14 ++
 parse-options.h |  7 +++
 2 files changed, 9 insertions(+), 12 deletions(-)

diff --git a/builtin/tag.c b/builtin/tag.c
index 2d6610a..767162e 100644
--- a/builtin/tag.c
+++ b/builtin/tag.c
@@ -595,23 +595,13 @@ int cmd_tag(int argc, const char **argv, const char 
*prefix)
 
OPT_GROUP(N_("Tag listing options")),
OPT_COLUMN(0, "column", &colopts, N_("show tag list in 
columns")),
+   OPT_CONTAINS(&with_commit, N_("print only tags that contain the 
commit")),
+   OPT_WITH(&with_commit, N_("print only tags that contain the 
commit")),
{
OPTION_CALLBACK, 0, "sort", &tag_sort, N_("type"), 
N_("sort tags"),
PARSE_OPT_NONEG, parse_opt_sort
},
{
-   OPTION_CALLBACK, 0, "contains", &with_commit, 
N_("commit"),
-   N_("print only tags that contain the commit"),
-   PARSE_OPT_LASTARG_DEFAULT,
-   parse_opt_commit_object_name, (intptr_t)"HEAD",
-   },
-   {
-   OPTION_CALLBACK, 0, "with", &with_commit, N_("commit"),
-   N_("print only tags that contain the commit"),
-   PARSE_OPT_HIDDEN | PARSE_OPT_LASTARG_DEFAULT,
-   parse_opt_commit_object_name, (intptr_t)"HEAD",
-   },
-   {
OPTION_CALLBACK, 0, "points-at", &points_at, 
N_("object"),
N_("print only tags of the object"), 0, 
parse_opt_object_name
},
diff --git a/parse-options.h b/parse-options.h
index 8542d9c..d76e907 100644
--- a/parse-options.h
+++ b/parse-options.h
@@ -243,5 +243,12 @@ extern int parse_opt_noop_cb(const struct option *, const 
char *, int);
OPT_COLOR_FLAG(0, "color", (var), (h))
 #define OPT_COLUMN(s, l, v, h) \
{ OPTION_CALLBACK, (s), (l), (v), N_("style"), (h), PARSE_OPT_OPTARG, 
parseopt_column_callback }
+#define _OPT_CONTAINS_OR_WITH(name, variable, help) \
+   { OPTION_CALLBACK, 0, name, (variable), N_("commit"), (help), \
+ PARSE_OPT_LASTARG_DEFAULT, \
+ parse_opt_commit_object_name, (intptr_t) "HEAD" \
+   }
+#define OPT_CONTAINS(v, h) _OPT_CONTAINS_OR_WITH("contains", v, h)
+#define OPT_WITH(v, h) _OPT_CONTAINS_OR_WITH("contains", v, h)
 
 #endif
-- 
2.4.3.435.g2403634.dirty

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


[PATCH v2 06/11] ref-filter: implement '--merged' and '--no-merged' options

2015-06-13 Thread Karthik Nayak
In 'branch -l' we have '--merged' option which only lists refs (branches)
merged into the named commit and '--no-merged' option which only lists
refs (branches) not merged into the named commit. Implement these two
options in ref-filter.{c,h} so that other commands can benefit from this.

Based-on-patch-by: Jeff King 
Mentored-by: Christian Couder 
Mentored-by: Matthieu Moy 
Signed-off-by: Karthik Nayak 
---
 ref-filter.c | 68 
 ref-filter.h |  8 +++
 2 files changed, 72 insertions(+), 4 deletions(-)

diff --git a/ref-filter.c b/ref-filter.c
index 6502179..06328eb 100644
--- a/ref-filter.c
+++ b/ref-filter.c
@@ -9,6 +9,7 @@
 #include "tag.h"
 #include "quote.h"
 #include "ref-filter.h"
+#include "revision.h"
 
 typedef enum { FIELD_STR, FIELD_ULONG, FIELD_TIME } cmp_type;
 
@@ -889,6 +890,7 @@ static int ref_filter_handler(const char *refname, const 
struct object_id *oid,
struct ref_filter_cbdata *ref_cbdata = cb_data;
struct ref_filter *filter = ref_cbdata->filter;
struct ref_array_item *ref;
+   struct commit *commit = NULL;
 
if (flag & REF_BAD_NAME) {
  warning("ignoring ref with broken name %s", refname);
@@ -901,12 +903,19 @@ static int ref_filter_handler(const char *refname, const 
struct object_id *oid,
if (!match_points_at(&filter->points_at, oid->hash, refname))
return 0;
 
+   if (filter->merge_commit) {
+   commit = lookup_commit_reference_gently(oid->hash, 1);
+   if (!commit)
+   return 0;
+   }
+
/*
 * We do not open the object yet; sort may only need refname
 * to do its job and the resulting list may yet to be pruned
 * by maxcount logic.
 */
ref = new_ref_array_item(refname, oid->hash, flag);
+   ref->commit = commit;
 
REALLOC_ARRAY(ref_cbdata->array->items, ref_cbdata->array->nr + 1);
ref_cbdata->array->items[ref_cbdata->array->nr++] = ref;
@@ -932,6 +941,50 @@ void ref_array_clear(struct ref_array *array)
array->nr = array->alloc = 0;
 }
 
+static void do_merge_filter(struct ref_filter_cbdata *ref_cbdata)
+{
+   struct rev_info revs;
+   int i, old_nr;
+   struct ref_filter *filter = ref_cbdata->filter;
+   struct ref_array *array = ref_cbdata->array;
+   struct commit_list *p, *to_clear = NULL;
+
+   init_revisions(&revs, NULL);
+
+   for (i = 0; i < array->nr; i++) {
+   struct ref_array_item *item = array->items[i];
+   add_pending_object(&revs, &item->commit->object, item->refname);
+   commit_list_insert(item->commit, &to_clear);
+   }
+
+   filter->merge_commit->object.flags |= UNINTERESTING;
+   add_pending_object(&revs, &filter->merge_commit->object, "");
+
+   revs.limited = 1;
+   if (prepare_revision_walk(&revs))
+   die(_("revision walk setup failed"));
+
+   old_nr = array->nr;
+   array->nr = 0;
+
+   for (i = 0; i < old_nr; i++) {
+   struct ref_array_item *item = array->items[i];
+   struct commit *commit = item->commit;
+
+   int is_merged = !!(commit->object.flags & UNINTERESTING);
+
+   if (is_merged == (filter->merge == REF_FILTER_MERGED_INCLUDE))
+   array->items[array->nr++] = array->items[i];
+   else
+   free_array_item(item);
+   }
+
+   for (p = to_clear; p; p = p->next)
+   clear_commit_marks(p->item, ALL_REV_FLAGS);
+   clear_commit_marks(filter->merge_commit, ALL_REV_FLAGS);
+   free_commit_list(to_clear);
+}
+
 /*
  * API for filtering a set of refs. Based on the type of refs the user
  * has requested, we iterate through those refs and apply filters
@@ -941,17 +994,24 @@ void ref_array_clear(struct ref_array *array)
 int filter_refs(struct ref_array *array, struct ref_filter *filter, unsigned 
int type)
 {
struct ref_filter_cbdata ref_cbdata;
+   int ret = 0;
 
ref_cbdata.array = array;
ref_cbdata.filter = filter;
 
+   /*  Simple per-ref filtering */
if (type & (FILTER_REFS_ALL | FILTER_REFS_INCLUDE_BROKEN))
-   return for_each_rawref(ref_filter_handler, &ref_cbdata);
+   ret = for_each_rawref(ref_filter_handler, &ref_cbdata);
else if (type & FILTER_REFS_ALL)
-   return for_each_ref(ref_filter_handler, &ref_cbdata);
-   else
+   ret = for_each_ref(ref_filter_handler, &ref_cbdata);
+   else if (type)
die("filter_refs: invalid type");
-   return 0;
+
+   /*  Filters that need revision walking */
+   if (filter->merge_commit)
+   do_merge_filter(&ref_cbdata);
+
+   return ret;
 }
 
 static int cmp_ref_sorting(struct ref_sorting *s, struct ref_array_item *a, 
struct ref_array_item *b)
diff --git a/ref-filter.h b/ref-f

[PATCH v2 05/11] ref-filter: add parse_opt_merge_filter()

2015-06-13 Thread Karthik Nayak
Add 'parse_opt_merge_filter()' to parse '--merged' and '--no-merged'
options and write MACROS for the same.

This is copied from 'builtin/branch.c' which will eventually be removed
when we port 'branch.c' to use ref-filter APIs.

Based-on-patch-by: Jeff King 
Mentored-by: Christian Couder 
Mentored-by: Matthieu Moy 
Signed-off-by: Karthik Nayak 
---
 builtin/branch.c |  4 
 ref-filter.c | 21 +
 ref-filter.h | 14 ++
 3 files changed, 39 insertions(+)

diff --git a/builtin/branch.c b/builtin/branch.c
index b42e5b6..ddd90e6 100644
--- a/builtin/branch.c
+++ b/builtin/branch.c
@@ -745,6 +745,10 @@ static void rename_branch(const char *oldname, const char 
*newname, int force)
strbuf_release(&newsection);
 }
 
+/*
+ * This function is duplicated in ref-filter. It will eventually be removed
+ * when we port branch.c to use ref-filter APIs.
+ */
 static int opt_parse_merge_filter(const struct option *opt, const char *arg, 
int unset)
 {
merge_filter = ((opt->long_name[0] == 'n')
diff --git a/ref-filter.c b/ref-filter.c
index 591e281..6502179 100644
--- a/ref-filter.c
+++ b/ref-filter.c
@@ -1125,3 +1125,24 @@ int parse_opt_ref_sorting(const struct option *opt, 
const char *arg, int unset)
s->atom = parse_ref_filter_atom(arg, arg+len);
return 0;
 }
+
+int parse_opt_merge_filter(const struct option *opt, const char *arg, int 
unset)
+{
+   struct ref_filter *rf = opt->value;
+   unsigned char sha1[20];
+
+   rf->merge = starts_with(opt->long_name, "no")
+   ? REF_FILTER_MERGED_OMIT
+   : REF_FILTER_MERGED_INCLUDE;
+
+   if (!arg)
+   arg = "HEAD";
+   if (get_sha1(arg, sha1))
+   die(_("malformed object name %s"), arg);
+
+   rf->merge_commit = lookup_commit_reference_gently(sha1, 0);
+   if (!rf->merge_commit)
+   return opterror(opt, "must point to a commit", 0);
+
+   return 0;
+}
diff --git a/ref-filter.h b/ref-filter.h
index c2856b8..799e118 100644
--- a/ref-filter.h
+++ b/ref-filter.h
@@ -50,6 +50,18 @@ struct ref_filter_cbdata {
struct ref_filter *filter;
 };
 
+/*  Macros for checking --merged and --no-merged options */
+#define OPT_NO_MERGED(filter, h) \
+   { OPTION_CALLBACK, 0, "no-merged", (filter), N_("commit"), (h), \
+ PARSE_OPT_LASTARG_DEFAULT | PARSE_OPT_NONEG, \
+ parse_opt_merge_filter, (intptr_t) "HEAD" \
+   }
+#define OPT_MERGED(filter, h) \
+   { OPTION_CALLBACK, 0, "merged", (filter), N_("commit"), (h), \
+ PARSE_OPT_LASTARG_DEFAULT | PARSE_OPT_NONEG, \
+ parse_opt_merge_filter, (intptr_t) "HEAD" \
+   }
+
 /*
  * API for filtering a set of refs. Based on the type of refs the user
  * has requested, we iterate through those refs and apply filters
@@ -71,5 +83,7 @@ void show_ref_array_item(struct ref_array_item *info, const 
char *format, int qu
 int parse_opt_ref_sorting(const struct option *opt, const char *arg, int 
unset);
 /*  Default sort option based on refname */
 struct ref_sorting *ref_default_sorting(void);
+/*  Function to parse --merged and --no-merged options */
+int parse_opt_merge_filter(const struct option *opt, const char *arg, int 
unset);
 
 #endif /*  REF_FILTER_H  */
-- 
2.4.3.435.g2403634.dirty

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


[PATCH v2 01/11] t6301: for-each-ref tests for ref-filter APIs

2015-06-13 Thread Karthik Nayak
Add tests for for-each-ref which utilizes the ref-filter APIs.

Based-on-patch-by: Jeff King 
Mentored-by: Christian Couder 
Mentored-by: Matthieu Moy 
Signed-off-by: Karthik Nayak 
---
 t/t6301-for-each-ref-filter.sh | 35 +++
 1 file changed, 35 insertions(+)
 create mode 100644 t/t6301-for-each-ref-filter.sh

diff --git a/t/t6301-for-each-ref-filter.sh b/t/t6301-for-each-ref-filter.sh
new file mode 100644
index 000..5bd49b3
--- /dev/null
+++ b/t/t6301-for-each-ref-filter.sh
@@ -0,0 +1,35 @@
+#!/bin/sh
+
+test_description='test for-each-refs usage of ref-filter APIs'
+
+. ./test-lib.sh
+. "$TEST_DIRECTORY"/lib-gpg.sh
+
+test_expect_success 'setup some history and refs' '
+   test_commit one &&
+   test_commit two &&
+   test_commit three &&
+   git checkout -b side &&
+   test_commit four &&
+   git checkout master &&
+   git update-ref refs/odd/spot master
+'
+test_expect_success 'filtering by leading name' '
+   cat >expect <<-\EOF &&
+   refs/heads/master
+   refs/heads/side
+   EOF
+   git for-each-ref --format="%(refname)" refs/heads >actual &&
+   test_cmp expect actual
+'
+
+test_expect_success 'filtering with fnmatch' '
+   cat >expect <<-\EOF &&
+   refs/tags/three
+   refs/tags/two
+   EOF
+   git for-each-ref --format="%(refname)" refs/tags/t* >actual &&
+   test_cmp expect actual
+'
+
+test_done
-- 
2.4.3.435.g2403634.dirty

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


[PATCH v2 04/11] for-each-ref: add '--points-at' option

2015-06-13 Thread Karthik Nayak
Add the '--points-at' option provided by 'ref-filter'. The
option lets the user to pick only refs which point to a particular
commit.

Add documentation and tests for the same.

Based-on-patch-by: Jeff King 
Mentored-by: Christian Couder 
Mentored-by: Matthieu Moy 
Signed-off-by: Karthik Nayak 
---
 Documentation/git-for-each-ref.txt |  3 +++
 builtin/for-each-ref.c |  9 +++--
 t/t6301-for-each-ref-filter.sh | 10 ++
 3 files changed, 20 insertions(+), 2 deletions(-)

diff --git a/Documentation/git-for-each-ref.txt 
b/Documentation/git-for-each-ref.txt
index 7f8d9a5..0524ac4 100644
--- a/Documentation/git-for-each-ref.txt
+++ b/Documentation/git-for-each-ref.txt
@@ -10,6 +10,7 @@ SYNOPSIS
 [verse]
 'git for-each-ref' [--count=] [--shell|--perl|--python|--tcl]
   [(--sort=)...] [--format=] [...]
+  [--points-at ]
 
 DESCRIPTION
 ---
@@ -62,6 +63,8 @@ OPTIONS
the specified host language.  This is meant to produce
a scriptlet that can directly be `eval`ed.
 
+--points-at ::
+   Only list refs of the given object.
 
 FIELD NAMES
 ---
diff --git a/builtin/for-each-ref.c b/builtin/for-each-ref.c
index 7919206..2dee149 100644
--- a/builtin/for-each-ref.c
+++ b/builtin/for-each-ref.c
@@ -7,6 +7,7 @@
 
 static char const * const for_each_ref_usage[] = {
N_("git for-each-ref [] []"),
+   N_("git for-each-ref [--points-at ]"),
NULL
 };
 
@@ -34,9 +35,15 @@ int cmd_for_each_ref(int argc, const char **argv, const char 
*prefix)
OPT_STRING(  0 , "format", &format, N_("format"), N_("format to 
use for the output")),
OPT_CALLBACK(0 , "sort", sorting_tail, N_("key"),
N_("field name to sort on"), 
&parse_opt_ref_sorting),
+   OPT_CALLBACK(0, "points-at", &filter.points_at,
+N_("object"), N_("print only refs of the object"),
+parse_opt_object_name),
OPT_END(),
};
 
+   memset(&array, 0, sizeof(array));
+   memset(&filter, 0, sizeof(filter));
+
parse_options(argc, argv, prefix, opts, for_each_ref_usage, 0);
if (maxcount < 0) {
error("invalid --count argument: `%d'", maxcount);
@@ -55,8 +62,6 @@ int cmd_for_each_ref(int argc, const char **argv, const char 
*prefix)
/* for warn_ambiguous_refs */
git_config(git_default_config, NULL);
 
-   memset(&array, 0, sizeof(array));
-   memset(&filter, 0, sizeof(filter));
filter.name_patterns = argv;
filter_refs(&array, &filter, FILTER_REFS_ALL | 
FILTER_REFS_INCLUDE_BROKEN);
ref_array_sort(sorting, &array);
diff --git a/t/t6301-for-each-ref-filter.sh b/t/t6301-for-each-ref-filter.sh
index 5bd49b3..3a1c3f6 100644
--- a/t/t6301-for-each-ref-filter.sh
+++ b/t/t6301-for-each-ref-filter.sh
@@ -32,4 +32,14 @@ test_expect_success 'filtering with fnmatch' '
test_cmp expect actual
 '
 
+test_expect_success 'filtering with --points-at' '
+   cat >expect <<-\EOF &&
+   refs/heads/master
+   refs/odd/spot
+   refs/tags/three
+   EOF
+   git for-each-ref --format="%(refname)" --points-at=master >actual &&
+   test_cmp expect actual
+'
+
 test_done
-- 
2.4.3.435.g2403634.dirty

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


[PATCH v2 02/11] tag: libify parse_opt_points_at()

2015-06-13 Thread Karthik Nayak
Rename 'parse_opt_points_at()' to 'parse_opt_object_name()' and
move it from 'tag.c' to 'parse-options'. This now acts as a common
parse_opt function which accepts an objectname and stores it into
a sha1_array.

Based-on-patch-by: Jeff King 
Mentored-by: Christian Couder 
Mentored-by: Matthieu Moy 
Signed-off-by: Karthik Nayak 
---
 builtin/tag.c  | 21 ++---
 parse-options-cb.c | 17 +
 parse-options.h|  1 +
 3 files changed, 20 insertions(+), 19 deletions(-)

diff --git a/builtin/tag.c b/builtin/tag.c
index 5f6cdc5..e36c43e 100644
--- a/builtin/tag.c
+++ b/builtin/tag.c
@@ -546,23 +546,6 @@ static int strbuf_check_tag_ref(struct strbuf *sb, const 
char *name)
return check_refname_format(sb->buf, 0);
 }
 
-static int parse_opt_points_at(const struct option *opt 
__attribute__((unused)),
-   const char *arg, int unset)
-{
-   unsigned char sha1[20];
-
-   if (unset) {
-   sha1_array_clear(&points_at);
-   return 0;
-   }
-   if (!arg)
-   return error(_("switch 'points-at' requires an object"));
-   if (get_sha1(arg, sha1))
-   return error(_("malformed object name '%s'"), arg);
-   sha1_array_append(&points_at, sha1);
-   return 0;
-}
-
 static int parse_opt_sort(const struct option *opt, const char *arg, int unset)
 {
int *sort = opt->value;
@@ -625,8 +608,8 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
parse_opt_with_commit, (intptr_t)"HEAD",
},
{
-   OPTION_CALLBACK, 0, "points-at", NULL, N_("object"),
-   N_("print only tags of the object"), 0, 
parse_opt_points_at
+   OPTION_CALLBACK, 0, "points-at", &points_at, 
N_("object"),
+   N_("print only tags of the object"), 0, 
parse_opt_object_name
},
OPT_END()
};
diff --git a/parse-options-cb.c b/parse-options-cb.c
index be8c413..de75411 100644
--- a/parse-options-cb.c
+++ b/parse-options-cb.c
@@ -4,6 +4,7 @@
 #include "commit.h"
 #include "color.h"
 #include "string-list.h"
+#include "sha1-array.h"
 
 /*- some often used options -*/
 
@@ -92,6 +93,22 @@ int parse_opt_with_commit(const struct option *opt, const 
char *arg, int unset)
return 0;
 }
 
+int parse_opt_object_name(const struct option *opt, const char *arg, int unset)
+{
+   unsigned char sha1[20];
+
+   if (unset) {
+   sha1_array_clear(opt->value);
+   return 0;
+   }
+   if (!arg)
+   return -1;
+   if (get_sha1(arg, sha1))
+   return error(_("malformed object name '%s'"), arg);
+   sha1_array_append(opt->value, sha1);
+   return 0;
+}
+
 int parse_opt_tertiary(const struct option *opt, const char *arg, int unset)
 {
int *target = opt->value;
diff --git a/parse-options.h b/parse-options.h
index c71e9da..36c71fe 100644
--- a/parse-options.h
+++ b/parse-options.h
@@ -220,6 +220,7 @@ extern int parse_opt_approxidate_cb(const struct option *, 
const char *, int);
 extern int parse_opt_expiry_date_cb(const struct option *, const char *, int);
 extern int parse_opt_color_flag_cb(const struct option *, const char *, int);
 extern int parse_opt_verbosity_cb(const struct option *, const char *, int);
+extern int parse_opt_object_name(const struct option *, const char *, int);
 extern int parse_opt_with_commit(const struct option *, const char *, int);
 extern int parse_opt_tertiary(const struct option *, const char *, int);
 extern int parse_opt_string_list(const struct option *, const char *, int);
-- 
2.4.3.435.g2403634.dirty

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


[PATCH v2 03/11] ref-filter: implement '--points-at' option

2015-06-13 Thread Karthik Nayak
In 'tag -l' we have '--points-at' option which lets users
list only tags which point to a particular commit. Implement
this option in 'ref-filter.{c,h}' so that other commands can
benefit from this.

This is duplicated from tag.c, we will eventually remove that
when we port tag.c to use ref-filter APIs.

Based-on-patch-by: Jeff King 
Mentored-by: Christian Couder 
Mentored-by: Matthieu Moy 
Signed-off-by: Karthik Nayak 
---
 builtin/tag.c |  4 
 ref-filter.c  | 26 ++
 ref-filter.h  |  1 +
 3 files changed, 31 insertions(+)

diff --git a/builtin/tag.c b/builtin/tag.c
index e36c43e..280981f 100644
--- a/builtin/tag.c
+++ b/builtin/tag.c
@@ -56,6 +56,10 @@ static int match_pattern(const char **patterns, const char 
*ref)
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)
 {
diff --git a/ref-filter.c b/ref-filter.c
index 43502a4..591e281 100644
--- a/ref-filter.c
+++ b/ref-filter.c
@@ -842,6 +842,29 @@ static int match_name_as_path(const char **pattern, const 
char *refname)
return 0;
 }
 
+/*
+ * Given a ref (sha1, refname) see if it points to a one of the sha1s
+ * in a sha1_array.
+ */
+static int match_points_at(struct sha1_array *points_at, const unsigned char 
*sha1,
+  const char *refname)
+{
+   struct object *obj;
+
+   if (!points_at || !points_at->nr)
+   return 1;
+
+   if (sha1_array_lookup(points_at, sha1) >= 0)
+   return 1;
+
+   obj = parse_object_or_die(sha1, refname);
+   if (obj->type == OBJ_TAG &&
+   sha1_array_lookup(points_at, ((struct tag *)obj)->tagged->sha1) >= 
0)
+   return 1;
+
+   return 0;
+}
+
 /* Allocate space for a new ref_array_item and copy the objectname and flag to 
it */
 static struct ref_array_item *new_ref_array_item(const char *refname,
 const unsigned char 
*objectname,
@@ -875,6 +898,9 @@ static int ref_filter_handler(const char *refname, const 
struct object_id *oid,
if (*filter->name_patterns && 
!match_name_as_path(filter->name_patterns, refname))
return 0;
 
+   if (!match_points_at(&filter->points_at, oid->hash, refname))
+   return 0;
+
/*
 * We do not open the object yet; sort may only need refname
 * to do its job and the resulting list may yet to be pruned
diff --git a/ref-filter.h b/ref-filter.h
index 6997984..c2856b8 100644
--- a/ref-filter.h
+++ b/ref-filter.h
@@ -42,6 +42,7 @@ struct ref_array {
 
 struct ref_filter {
const char **name_patterns;
+   struct sha1_array points_at;
 };
 
 struct ref_filter_cbdata {
-- 
2.4.3.435.g2403634.dirty

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


[PATCH v2 00/11] add options to for-each-ref

2015-06-13 Thread karthik nayak
This is continuation of the patch series 'Create ref-filter from for-each-ref'
found at : http://article.gmane.org/gmane.comp.version-control.git/271563

The previous version of this series can be found at :
http://www.mail-archive.com/git%40vger.kernel.org/msg70929.html

Changes made:
* Added tests
* Added comments to filter_refs()
* Small structural changes
* Various coding style fixes

Thanks to Junio C Hamano, Matthieu Moy, and Christian Couder for all
the suggestions.

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


[PATCH v8 03/11] for-each-ref: rename 'refinfo' to 'ref_array_item'

2015-06-13 Thread Karthik Nayak
Rename 'refinfo' to 'ref_array_item' as a preparatory step for
introduction of new structures in the forthcoming patch.

Re-order the fields in 'ref_array_item' so that refname can be
eventually converted to a FLEX_ARRAY.

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

diff --git a/builtin/for-each-ref.c b/builtin/for-each-ref.c
index f0d7d44..d1b7e81 100644
--- a/builtin/for-each-ref.c
+++ b/builtin/for-each-ref.c
@@ -31,12 +31,12 @@ struct ref_sort {
unsigned reverse : 1;
 };
 
-struct refinfo {
-   char *refname;
+struct ref_array_item {
unsigned char objectname[20];
int flag;
const char *symref;
struct atom_value *value;
+   char *refname;
 };
 
 static struct {
@@ -86,7 +86,7 @@ static struct {
  * a "*" to denote deref_tag().
  *
  * We parse given format string and sort specifiers, and make a list
- * of properties that we need to extract out of objects.  refinfo
+ * of properties that we need to extract out of objects.  ref_array_item
  * structure will hold an array of values extracted that can be
  * indexed with the "atom number", which is an index into this
  * array.
@@ -623,7 +623,7 @@ static inline char *copy_advance(char *dst, const char *src)
 /*
  * Parse the object referred by ref, and grab needed value.
  */
-static void populate_value(struct refinfo *ref)
+static void populate_value(struct ref_array_item *ref)
 {
void *buf;
struct object *obj;
@@ -835,7 +835,7 @@ static void populate_value(struct refinfo *ref)
  * Given a ref, return the value for the atom.  This lazily gets value
  * out of the object by calling populate value.
  */
-static void get_value(struct refinfo *ref, int atom, struct atom_value **v)
+static void get_value(struct ref_array_item *ref, int atom, struct atom_value 
**v)
 {
if (!ref->value) {
populate_value(ref);
@@ -845,7 +845,7 @@ static void get_value(struct refinfo *ref, int atom, struct 
atom_value **v)
 }
 
 struct grab_ref_cbdata {
-   struct refinfo **grab_array;
+   struct ref_array_item **grab_array;
const char **grab_pattern;
int grab_cnt;
 };
@@ -875,12 +875,12 @@ static int match_name_as_path(const char **pattern, const 
char *refname)
return 0;
 }
 
-/* Allocate space for a new refinfo and copy the objectname and flag to it */
-static struct refinfo *new_refinfo(const char *refname,
-  const unsigned char *objectname,
-  int flag)
+/* Allocate space for a new ref_array_item and copy the objectname and flag to 
it */
+static struct ref_array_item *new_ref_array_item(const char *refname,
+const unsigned char 
*objectname,
+int flag)
 {
-   struct refinfo *ref = xcalloc(1, sizeof(struct refinfo));
+   struct ref_array_item *ref = xcalloc(1, sizeof(struct ref_array_item));
ref->refname = xstrdup(refname);
hashcpy(ref->objectname, objectname);
ref->flag = flag;
@@ -896,7 +896,7 @@ static int grab_single_ref(const char *refname, const 
struct object_id *oid,
   int flag, void *cb_data)
 {
struct grab_ref_cbdata *cb = cb_data;
-   struct refinfo *ref;
+   struct ref_array_item *ref;
 
if (flag & REF_BAD_NAME) {
  warning("ignoring ref with broken name %s", refname);
@@ -911,14 +911,14 @@ static int grab_single_ref(const char *refname, const 
struct object_id *oid,
 * to do its job and the resulting list may yet to be pruned
 * by maxcount logic.
 */
-   ref = new_refinfo(refname, oid->hash, flag);
+   ref = new_ref_array_item(refname, oid->hash, flag);
 
REALLOC_ARRAY(cb->grab_array, cb->grab_cnt + 1);
cb->grab_array[cb->grab_cnt++] = ref;
return 0;
 }
 
-static int cmp_ref_sort(struct ref_sort *s, struct refinfo *a, struct refinfo 
*b)
+static int cmp_ref_sort(struct ref_sort *s, struct ref_array_item *a, struct 
ref_array_item *b)
 {
struct atom_value *va, *vb;
int cmp;
@@ -945,8 +945,8 @@ static int cmp_ref_sort(struct ref_sort *s, struct refinfo 
*a, struct refinfo *b
 static struct ref_sort *ref_sort;
 static int compare_refs(const void *a_, const void *b_)
 {
-   struct refinfo *a = *((struct refinfo **)a_);
-   struct refinfo *b = *((struct refinfo **)b_);
+   struct ref_array_item *a = *((struct ref_array_item **)a_);
+   struct ref_array_item *b = *((struct ref_array_item **)b_);
struct ref_sort *s;
 
for (s = ref_sort; s; s = s->next) {
@@ -957,10 +957,10 @@ static int compare_refs(const void *a_, const void *b_)
return 0;
 }
 
-static void sort_refs(struct ref_sort *sort, struct refinfo **refs, int 
num_

[PATCH v8 09/11] ref-filter: move code from 'for-each-ref'

2015-06-13 Thread Karthik Nayak
Move most of the code from 'for-each-ref' to 'ref-filter' to make
it publicly available to other commands, this is to unify the code
of 'tag -l', 'branch -l' and 'for-each-ref' so that they can share
their implementations with each other.

Add 'ref-filter' to the Makefile, this completes the movement of code
from 'for-each-ref' to 'ref-filter'.

Mentored-by: Christian Couder 
Mentored-by: Matthieu Moy 
Signed-off-by: Karthik Nayak 
---
 Makefile   |1 +
 builtin/for-each-ref.c | 1074 ---
 ref-filter.c   | 1078 
 3 files changed, 1079 insertions(+), 1074 deletions(-)
 create mode 100644 ref-filter.c

diff --git a/Makefile b/Makefile
index 54ec511..d715b66 100644
--- a/Makefile
+++ b/Makefile
@@ -762,6 +762,7 @@ LIB_OBJS += reachable.o
 LIB_OBJS += read-cache.o
 LIB_OBJS += reflog-walk.o
 LIB_OBJS += refs.o
+LIB_OBJS += ref-filter.o
 LIB_OBJS += remote.o
 LIB_OBJS += replace_object.o
 LIB_OBJS += rerere.o
diff --git a/builtin/for-each-ref.c b/builtin/for-each-ref.c
index 26485b9..637fc4a 100644
--- a/builtin/for-each-ref.c
+++ b/builtin/for-each-ref.c
@@ -2,1083 +2,9 @@
 #include "cache.h"
 #include "refs.h"
 #include "object.h"
-#include "tag.h"
-#include "commit.h"
-#include "tree.h"
-#include "blob.h"
-#include "quote.h"
 #include "parse-options.h"
-#include "remote.h"
-#include "color.h"
 #include "ref-filter.h"
 
-typedef enum { FIELD_STR, FIELD_ULONG, FIELD_TIME } cmp_type;
-
-static struct {
-   const char *name;
-   cmp_type cmp_type;
-} valid_atom[] = {
-   { "refname" },
-   { "objecttype" },
-   { "objectsize", FIELD_ULONG },
-   { "objectname" },
-   { "tree" },
-   { "parent" },
-   { "numparent", FIELD_ULONG },
-   { "object" },
-   { "type" },
-   { "tag" },
-   { "author" },
-   { "authorname" },
-   { "authoremail" },
-   { "authordate", FIELD_TIME },
-   { "committer" },
-   { "committername" },
-   { "committeremail" },
-   { "committerdate", FIELD_TIME },
-   { "tagger" },
-   { "taggername" },
-   { "taggeremail" },
-   { "taggerdate", FIELD_TIME },
-   { "creator" },
-   { "creatordate", FIELD_TIME },
-   { "subject" },
-   { "body" },
-   { "contents" },
-   { "contents:subject" },
-   { "contents:body" },
-   { "contents:signature" },
-   { "upstream" },
-   { "push" },
-   { "symref" },
-   { "flag" },
-   { "HEAD" },
-   { "color" },
-};
-
-/*
- * An atom is a valid field atom listed above, possibly prefixed with
- * a "*" to denote deref_tag().
- *
- * We parse given format string and sort specifiers, and make a list
- * of properties that we need to extract out of objects.  ref_array_item
- * structure will hold an array of values extracted that can be
- * indexed with the "atom number", which is an index into this
- * array.
- */
-static const char **used_atom;
-static cmp_type *used_atom_type;
-static int used_atom_cnt, need_tagged, need_symref;
-static int need_color_reset_at_eol;
-
-/*
- * Used to parse format string and sort specifiers
- */
-int parse_ref_filter_atom(const char *atom, const char *ep)
-{
-   const char *sp;
-   int i, at;
-
-   sp = atom;
-   if (*sp == '*' && sp < ep)
-   sp++; /* deref */
-   if (ep <= sp)
-   die("malformed field name: %.*s", (int)(ep-atom), atom);
-
-   /* Do we have the atom already used elsewhere? */
-   for (i = 0; i < used_atom_cnt; i++) {
-   int len = strlen(used_atom[i]);
-   if (len == ep - atom && !memcmp(used_atom[i], atom, len))
-   return i;
-   }
-
-   /* Is the atom a valid one? */
-   for (i = 0; i < ARRAY_SIZE(valid_atom); i++) {
-   int len = strlen(valid_atom[i].name);
-   /*
-* If the atom name has a colon, strip it and everything after
-* it off - it specifies the format for this entry, and
-* shouldn't be used for checking against the valid_atom
-* table.
-*/
-   const char *formatp = strchr(sp, ':');
-   if (!formatp || ep < formatp)
-   formatp = ep;
-   if (len == formatp - sp && !memcmp(valid_atom[i].name, sp, len))
-   break;
-   }
-
-   if (ARRAY_SIZE(valid_atom) <= i)
-   die("unknown field name: %.*s", (int)(ep-atom), atom);
-
-   /* Add it in, including the deref prefix */
-   at = used_atom_cnt;
-   used_atom_cnt++;
-   REALLOC_ARRAY(used_atom, used_atom_cnt);
-   REALLOC_ARRAY(used_atom_type, used_atom_cnt);
-   used_atom[at] = xmemdupz(atom, ep - atom);
-   used_atom_type[at] = valid_atom[i].cmp_type;
-   if (*atom == '*')
-   need_tagged = 1;
-   if (!strcmp(used_atom[at], "symref"))
-  

[PATCH v8 05/11] for-each-ref: introduce 'ref_array_clear()'

2015-06-13 Thread Karthik Nayak
Introduce and implement 'ref_array_clear()' which will free
all allocated memory for 'ref_array'.

Mentored-by: Christian Couder 
Mentored-by: Matthieu Moy 
Signed-off-by: Karthik Nayak 
---
 builtin/for-each-ref.c | 21 +
 1 file changed, 21 insertions(+)

diff --git a/builtin/for-each-ref.c b/builtin/for-each-ref.c
index 822838a..bb83f7a 100644
--- a/builtin/for-each-ref.c
+++ b/builtin/for-each-ref.c
@@ -927,6 +927,26 @@ static int grab_single_ref(const char *refname, const 
struct object_id *oid,
return 0;
 }
 
+/*  Free memory allocated for a ref_array_item */
+static void free_array_item(struct ref_array_item *item)
+{
+   free((char *)item->symref);
+   free(item->refname);
+   free(item);
+}
+
+/* Free all memory allocated for ref_array */
+void ref_array_clear(struct ref_array *array)
+{
+   int i;
+
+   for (i = 0; i < array->nr; i++)
+   free_array_item(array->items[i]);
+   free(array->items);
+   array->items = NULL;
+   array->nr = array->alloc = 0;
+}
+
 static int cmp_ref_sort(struct ref_sort *s, struct ref_array_item *a, struct 
ref_array_item *b)
 {
struct atom_value *va, *vb;
@@ -1157,5 +1177,6 @@ int cmd_for_each_ref(int argc, const char **argv, const 
char *prefix)
maxcount = ref_cbdata.array.nr;
for (i = 0; i < maxcount; i++)
show_ref(ref_cbdata.array.items[i], format, quote_style);
+   ref_array_clear(&ref_cbdata.array);
return 0;
 }
-- 
2.4.3.435.g2403634.dirty

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


[PATCH v8 04/11] for-each-ref: introduce new structures for better organisation

2015-06-13 Thread Karthik Nayak
Introduce 'ref_filter_cbdata' which will hold 'ref_filter'
(conditions to filter the refs on) and 'ref_array' (the array
of ref_array_items). Modify the code to use these new structures.

This is a preparatory patch to eventually move code from 'for-each-ref'
to 'ref-filter' and make it publicly available.

Mentored-by: Christian Couder 
Mentored-by: Matthieu Moy 
Signed-off-by: Karthik Nayak 
---
 builtin/for-each-ref.c | 54 --
 1 file changed, 30 insertions(+), 24 deletions(-)

diff --git a/builtin/for-each-ref.c b/builtin/for-each-ref.c
index d1b7e81..822838a 100644
--- a/builtin/for-each-ref.c
+++ b/builtin/for-each-ref.c
@@ -39,6 +39,20 @@ struct ref_array_item {
char *refname;
 };
 
+struct ref_array {
+   int nr, alloc;
+   struct ref_array_item **items;
+};
+
+struct ref_filter {
+   const char **name_patterns;
+};
+
+struct ref_filter_cbdata {
+   struct ref_array array;
+   struct ref_filter filter;
+};
+
 static struct {
const char *name;
cmp_type cmp_type;
@@ -844,12 +858,6 @@ static void get_value(struct ref_array_item *ref, int 
atom, struct atom_value **
*v = &ref->value[atom];
 }
 
-struct grab_ref_cbdata {
-   struct ref_array_item **grab_array;
-   const char **grab_pattern;
-   int grab_cnt;
-};
-
 /*
  * 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"
@@ -895,7 +903,8 @@ static struct ref_array_item *new_ref_array_item(const char 
*refname,
 static int grab_single_ref(const char *refname, const struct object_id *oid,
   int flag, void *cb_data)
 {
-   struct grab_ref_cbdata *cb = cb_data;
+   struct ref_filter_cbdata *ref_cbdata = cb_data;
+   struct ref_filter *filter = &ref_cbdata->filter;
struct ref_array_item *ref;
 
if (flag & REF_BAD_NAME) {
@@ -903,7 +912,7 @@ static int grab_single_ref(const char *refname, const 
struct object_id *oid,
  return 0;
}
 
-   if (*cb->grab_pattern && !match_name_as_path(cb->grab_pattern, refname))
+   if (*filter->name_patterns && 
!match_name_as_path(filter->name_patterns, refname))
return 0;
 
/*
@@ -913,8 +922,8 @@ static int grab_single_ref(const char *refname, const 
struct object_id *oid,
 */
ref = new_ref_array_item(refname, oid->hash, flag);
 
-   REALLOC_ARRAY(cb->grab_array, cb->grab_cnt + 1);
-   cb->grab_array[cb->grab_cnt++] = ref;
+   REALLOC_ARRAY(ref_cbdata->array.items, ref_cbdata->array.nr + 1);
+   ref_cbdata->array.items[ref_cbdata->array.nr++] = ref;
return 0;
 }
 
@@ -957,10 +966,10 @@ static int compare_refs(const void *a_, const void *b_)
return 0;
 }
 
-static void sort_refs(struct ref_sort *sort, struct ref_array_item **refs, int 
num_refs)
+static void sort_refs(struct ref_sort *sort, struct ref_array *array)
 {
ref_sort = sort;
-   qsort(refs, num_refs, sizeof(struct ref_array_item *), compare_refs);
+   qsort(array->items, array->nr, sizeof(struct ref_array_item *), 
compare_refs);
 }
 
 static void print_value(struct atom_value *v, int quote_style)
@@ -1096,12 +1105,11 @@ static char const * const for_each_ref_usage[] = {
 
 int cmd_for_each_ref(int argc, const char **argv, const char *prefix)
 {
-   int i, num_refs;
+   int i;
const char *format = "%(objectname) %(objecttype)\t%(refname)";
struct ref_sort *sort = NULL, **sort_tail = &sort;
int maxcount = 0, quote_style = 0;
-   struct ref_array_item **refs;
-   struct grab_ref_cbdata cbdata;
+   struct ref_filter_cbdata ref_cbdata;
 
struct option opts[] = {
OPT_BIT('s', "shell", "e_style,
@@ -1139,17 +1147,15 @@ int cmd_for_each_ref(int argc, const char **argv, const 
char *prefix)
/* for warn_ambiguous_refs */
git_config(git_default_config, NULL);
 
-   memset(&cbdata, 0, sizeof(cbdata));
-   cbdata.grab_pattern = argv;
-   for_each_rawref(grab_single_ref, &cbdata);
-   refs = cbdata.grab_array;
-   num_refs = cbdata.grab_cnt;
+   memset(&ref_cbdata, 0, sizeof(ref_cbdata));
+   ref_cbdata.filter.name_patterns = argv;
+   for_each_rawref(grab_single_ref, &ref_cbdata);
 
-   sort_refs(sort, refs, num_refs);
+   sort_refs(sort, &ref_cbdata.array);
 
-   if (!maxcount || num_refs < maxcount)
-   maxcount = num_refs;
+   if (!maxcount || ref_cbdata.array.nr < maxcount)
+   maxcount = ref_cbdata.array.nr;
for (i = 0; i < maxcount; i++)
-   show_ref(refs[i], format, quote_style);
+   show_ref(ref_cbdata.array.items[i], format, quote_style);
return 0;
 }
-- 
2.4.3.435.g2403634.dirty

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

[PATCH v8 11/11] ref-filter: make 'ref_array_item' use a FLEX_ARRAY for refname

2015-06-13 Thread Karthik Nayak
This would remove the need of using a pointer to store refname.

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

diff --git a/ref-filter.c b/ref-filter.c
index a1151e0..43502a4 100644
--- a/ref-filter.c
+++ b/ref-filter.c
@@ -847,8 +847,10 @@ static struct ref_array_item *new_ref_array_item(const 
char *refname,
 const unsigned char 
*objectname,
 int flag)
 {
-   struct ref_array_item *ref = xcalloc(1, sizeof(struct ref_array_item));
-   ref->refname = xstrdup(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';
hashcpy(ref->objectname, objectname);
ref->flag = flag;
 
@@ -889,7 +891,6 @@ static int ref_filter_handler(const char *refname, const 
struct object_id *oid,
 static void free_array_item(struct ref_array_item *item)
 {
free((char *)item->symref);
-   free(item->refname);
free(item);
 }
 
diff --git a/ref-filter.h b/ref-filter.h
index 697b609..6997984 100644
--- a/ref-filter.h
+++ b/ref-filter.h
@@ -32,7 +32,7 @@ struct ref_array_item {
int flag;
const char *symref;
struct atom_value *value;
-   char *refname;
+   char refname[FLEX_ARRAY];
 };
 
 struct ref_array {
-- 
2.4.3.435.g2403634.dirty

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


[PATCH v8 10/11] for-each-ref: introduce filter_refs()

2015-06-13 Thread Karthik Nayak
Introduce filter_refs() which will act as an API for filtering
a set of refs. Based on the type of refs the user has requested,
we iterate through those refs and apply filters as per the
given ref_filter structure and finally store the filtered refs
in the ref_array structure.

Currently this will wrap around ref_filter_handler(). Hence,
ref_filter_handler is made file scope static.

As users of this API will no longer send a ref_filter_cbdata
structure directly, we make the elements of ref_filter_cbdata
pointers. We can now use the information given by the users
to obtain our own ref_filter_cbdata structure. Changes are made to
support the change in ref_filter_cbdata structure.

Make 'for-each-ref' use this API.

Helped-by: Junio C Hamano 
Mentored-by: Christian Couder 
Mentored-by: Matthieu Moy 
Signed-off-by: Karthik Nayak 
---
 builtin/for-each-ref.c | 21 +++--
 ref-filter.c   | 30 ++
 ref-filter.h   | 16 
 3 files changed, 49 insertions(+), 18 deletions(-)

diff --git a/builtin/for-each-ref.c b/builtin/for-each-ref.c
index 637fc4a..7919206 100644
--- a/builtin/for-each-ref.c
+++ b/builtin/for-each-ref.c
@@ -16,7 +16,8 @@ int cmd_for_each_ref(int argc, const char **argv, const char 
*prefix)
const char *format = "%(objectname) %(objecttype)\t%(refname)";
struct ref_sorting *sorting = NULL, **sorting_tail = &sorting;
int maxcount = 0, quote_style = 0;
-   struct ref_filter_cbdata ref_cbdata;
+   struct ref_array array;
+   struct ref_filter filter;
 
struct option opts[] = {
OPT_BIT('s', "shell", "e_style,
@@ -54,16 +55,16 @@ int cmd_for_each_ref(int argc, const char **argv, const 
char *prefix)
/* for warn_ambiguous_refs */
git_config(git_default_config, NULL);
 
-   memset(&ref_cbdata, 0, sizeof(ref_cbdata));
-   ref_cbdata.filter.name_patterns = argv;
-   for_each_rawref(ref_filter_handler, &ref_cbdata);
+   memset(&array, 0, sizeof(array));
+   memset(&filter, 0, sizeof(filter));
+   filter.name_patterns = argv;
+   filter_refs(&array, &filter, FILTER_REFS_ALL | 
FILTER_REFS_INCLUDE_BROKEN);
+   ref_array_sort(sorting, &array);
 
-   ref_array_sort(sorting, &ref_cbdata.array);
-
-   if (!maxcount || ref_cbdata.array.nr < maxcount)
-   maxcount = ref_cbdata.array.nr;
+   if (!maxcount || array.nr < maxcount)
+   maxcount = array.nr;
for (i = 0; i < maxcount; i++)
-   show_ref_array_item(ref_cbdata.array.items[i], format, 
quote_style);
-   ref_array_clear(&ref_cbdata.array);
+   show_ref_array_item(array.items[i], format, quote_style);
+   ref_array_clear(&array);
return 0;
 }
diff --git a/ref-filter.c b/ref-filter.c
index f0dd0f2..a1151e0 100644
--- a/ref-filter.c
+++ b/ref-filter.c
@@ -859,10 +859,10 @@ static struct ref_array_item *new_ref_array_item(const 
char *refname,
  * A call-back given to for_each_ref().  Filter refs and keep them for
  * later object processing.
  */
-int ref_filter_handler(const char *refname, const struct object_id *oid, int 
flag, void *cb_data)
+static int ref_filter_handler(const char *refname, const struct object_id 
*oid, int flag, void *cb_data)
 {
struct ref_filter_cbdata *ref_cbdata = cb_data;
-   struct ref_filter *filter = &ref_cbdata->filter;
+   struct ref_filter *filter = ref_cbdata->filter;
struct ref_array_item *ref;
 
if (flag & REF_BAD_NAME) {
@@ -880,8 +880,8 @@ int ref_filter_handler(const char *refname, const struct 
object_id *oid, int fla
 */
ref = new_ref_array_item(refname, oid->hash, flag);
 
-   REALLOC_ARRAY(ref_cbdata->array.items, ref_cbdata->array.nr + 1);
-   ref_cbdata->array.items[ref_cbdata->array.nr++] = ref;
+   REALLOC_ARRAY(ref_cbdata->array->items, ref_cbdata->array->nr + 1);
+   ref_cbdata->array->items[ref_cbdata->array->nr++] = ref;
return 0;
 }
 
@@ -905,6 +905,28 @@ void ref_array_clear(struct ref_array *array)
array->nr = array->alloc = 0;
 }
 
+/*
+ * API for filtering a set of refs. Based on the type of refs the user
+ * has requested, we iterate through those refs and apply filters
+ * as per the given ref_filter structure and finally store the
+ * filtered refs in the ref_array structure.
+ */
+int filter_refs(struct ref_array *array, struct ref_filter *filter, unsigned 
int type)
+{
+   struct ref_filter_cbdata ref_cbdata;
+
+   ref_cbdata.array = array;
+   ref_cbdata.filter = filter;
+
+   if (type & (FILTER_REFS_ALL | FILTER_REFS_INCLUDE_BROKEN))
+   return for_each_rawref(ref_filter_handler, &ref_cbdata);
+   else if (type & FILTER_REFS_ALL)
+   return for_each_ref(ref_filter_handler, &ref_cbdata);
+   else
+   die("filter_refs: invalid type");
+   return 0;
+}
+
 static int cmp_ref_sorting(struct ref_sorting *s,

[PATCH v8 07/11] for-each-ref: rename variables called sort to sorting

2015-06-13 Thread Karthik Nayak
Rename all the variables called sort to sorting to match the
function/structure name changes made in the previous patch.

Mentored-by: Christian Couder 
Mentored-by: Matthieu Moy 
Signed-off-by: Karthik Nayak 
---
 builtin/for-each-ref.c | 28 ++--
 1 file changed, 14 insertions(+), 14 deletions(-)

diff --git a/builtin/for-each-ref.c b/builtin/for-each-ref.c
index 5700b25..d11059b 100644
--- a/builtin/for-each-ref.c
+++ b/builtin/for-each-ref.c
@@ -985,9 +985,9 @@ static int compare_refs(const void *a_, const void *b_)
return 0;
 }
 
-void ref_array_sort(struct ref_sorting *sort, struct ref_array *array)
+void ref_array_sort(struct ref_sorting *sorting, struct ref_array *array)
 {
-   ref_sorting = sort;
+   ref_sorting = sorting;
qsort(array->items, array->nr, sizeof(struct ref_array_item *), 
compare_refs);
 }
 
@@ -1089,16 +1089,16 @@ struct ref_sorting *ref_default_sorting(void)
 {
static const char cstr_name[] = "refname";
 
-   struct ref_sorting *sort = xcalloc(1, sizeof(*sort));
+   struct ref_sorting *sorting = xcalloc(1, sizeof(*sorting));
 
-   sort->next = NULL;
-   sort->atom = parse_ref_filter_atom(cstr_name, cstr_name + 
strlen(cstr_name));
-   return sort;
+   sorting->next = NULL;
+   sorting->atom = parse_ref_filter_atom(cstr_name, cstr_name + 
strlen(cstr_name));
+   return sorting;
 }
 
 int parse_opt_ref_sorting(const struct option *opt, const char *arg, int unset)
 {
-   struct ref_sorting **sort_tail = opt->value;
+   struct ref_sorting **sorting_tail = opt->value;
struct ref_sorting *s;
int len;
 
@@ -1106,8 +1106,8 @@ int parse_opt_ref_sorting(const struct option *opt, const 
char *arg, int unset)
return -1;
 
s = xcalloc(1, sizeof(*s));
-   s->next = *sort_tail;
-   *sort_tail = s;
+   s->next = *sorting_tail;
+   *sorting_tail = s;
 
if (*arg == '-') {
s->reverse = 1;
@@ -1127,7 +1127,7 @@ int cmd_for_each_ref(int argc, const char **argv, const 
char *prefix)
 {
int i;
const char *format = "%(objectname) %(objecttype)\t%(refname)";
-   struct ref_sorting *sort = NULL, **sort_tail = &sort;
+   struct ref_sorting *sorting = NULL, **sorting_tail = &sorting;
int maxcount = 0, quote_style = 0;
struct ref_filter_cbdata ref_cbdata;
 
@@ -1144,7 +1144,7 @@ int cmd_for_each_ref(int argc, const char **argv, const 
char *prefix)
OPT_GROUP(""),
OPT_INTEGER( 0 , "count", &maxcount, N_("show only  matched 
refs")),
OPT_STRING(  0 , "format", &format, N_("format"), N_("format to 
use for the output")),
-   OPT_CALLBACK(0 , "sort", sort_tail, N_("key"),
+   OPT_CALLBACK(0 , "sort", sorting_tail, N_("key"),
N_("field name to sort on"), 
&parse_opt_ref_sorting),
OPT_END(),
};
@@ -1161,8 +1161,8 @@ int cmd_for_each_ref(int argc, const char **argv, const 
char *prefix)
if (verify_ref_format(format))
usage_with_options(for_each_ref_usage, opts);
 
-   if (!sort)
-   sort = ref_default_sorting();
+   if (!sorting)
+   sorting = ref_default_sorting();
 
/* for warn_ambiguous_refs */
git_config(git_default_config, NULL);
@@ -1171,7 +1171,7 @@ int cmd_for_each_ref(int argc, const char **argv, const 
char *prefix)
ref_cbdata.filter.name_patterns = argv;
for_each_rawref(ref_filter_handler, &ref_cbdata);
 
-   ref_array_sort(sort, &ref_cbdata.array);
+   ref_array_sort(sorting, &ref_cbdata.array);
 
if (!maxcount || ref_cbdata.array.nr < maxcount)
maxcount = ref_cbdata.array.nr;
-- 
2.4.3.435.g2403634.dirty

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


[PATCH v8 08/11] ref-filter: add 'ref-filter.h'

2015-06-13 Thread Karthik Nayak
This is step one of creating a common library for 'for-each-ref',
'branch -l' and 'tag -l'. This creates a header file with the
functions and data structures that ref-filter will provide.
We move the data structures created in for-each-ref to this header
file.

Mentored-by: Christian Couder 
Mentored-by: Matthieu Moy 
Signed-off-by: Karthik Nayak 
---
 builtin/for-each-ref.c | 41 +--
 ref-filter.h   | 66 ++
 2 files changed, 67 insertions(+), 40 deletions(-)
 create mode 100644 ref-filter.h

diff --git a/builtin/for-each-ref.c b/builtin/for-each-ref.c
index d11059b..26485b9 100644
--- a/builtin/for-each-ref.c
+++ b/builtin/for-each-ref.c
@@ -10,49 +10,10 @@
 #include "parse-options.h"
 #include "remote.h"
 #include "color.h"
-
-/* Quoting styles */
-#define QUOTE_NONE 0
-#define QUOTE_SHELL 1
-#define QUOTE_PERL 2
-#define QUOTE_PYTHON 4
-#define QUOTE_TCL 8
+#include "ref-filter.h"
 
 typedef enum { FIELD_STR, FIELD_ULONG, FIELD_TIME } cmp_type;
 
-struct atom_value {
-   const char *s;
-   unsigned long ul; /* used for sorting when not FIELD_STR */
-};
-
-struct ref_sort {
-   struct ref_sort *next;
-   int atom; /* index into used_atom array */
-   unsigned reverse : 1;
-};
-
-struct ref_array_item {
-   unsigned char objectname[20];
-   int flag;
-   const char *symref;
-   struct atom_value *value;
-   char *refname;
-};
-
-struct ref_array {
-   int nr, alloc;
-   struct ref_array_item **items;
-};
-
-struct ref_filter {
-   const char **name_patterns;
-};
-
-struct ref_filter_cbdata {
-   struct ref_array array;
-   struct ref_filter filter;
-};
-
 static struct {
const char *name;
cmp_type cmp_type;
diff --git a/ref-filter.h b/ref-filter.h
new file mode 100644
index 000..506ac8f
--- /dev/null
+++ b/ref-filter.h
@@ -0,0 +1,66 @@
+#ifndef REF_FILTER_H
+#define REF_FILTER_H
+
+#include "sha1-array.h"
+#include "refs.h"
+#include "commit.h"
+#include "parse-options.h"
+
+/* Quoting styles */
+#define QUOTE_NONE 0
+#define QUOTE_SHELL 1
+#define QUOTE_PERL 2
+#define QUOTE_PYTHON 4
+#define QUOTE_TCL 8
+
+struct atom_value {
+   const char *s;
+   unsigned long ul; /* used for sorting when not FIELD_STR */
+};
+
+struct ref_sorting {
+   struct ref_sorting *next;
+   int atom; /* index into used_atom array (internal) */
+   unsigned reverse : 1;
+};
+
+struct ref_array_item {
+   unsigned char objectname[20];
+   int flag;
+   const char *symref;
+   struct atom_value *value;
+   char *refname;
+};
+
+struct ref_array {
+   int nr, alloc;
+   struct ref_array_item **items;
+};
+
+struct ref_filter {
+   const char **name_patterns;
+};
+
+struct ref_filter_cbdata {
+   struct ref_array array;
+   struct ref_filter filter;
+};
+
+/*  Callback function for for_each_*ref(). This filters the refs based on the 
filters set */
+int ref_filter_handler(const char *refname, const struct object_id *oid, int 
flag, void *cb_data);
+/*  Clear all memory allocated to ref_array */
+void ref_array_clear(struct ref_array *array);
+/*  Parse format string and sort specifiers */
+int parse_ref_filter_atom(const char *atom, const char *ep);
+/*  Used to verify if the given format is correct and to parse out the used 
atoms */
+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);
+/*  Callback function for parsing the sort option */
+int parse_opt_ref_sorting(const struct option *opt, const char *arg, int 
unset);
+/*  Default sort option based on refname */
+struct ref_sorting *ref_default_sorting(void);
+
+#endif /*  REF_FILTER_H  */
-- 
2.4.3.435.g2403634.dirty

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


[PATCH v8 06/11] for-each-ref: rename some functions and make them public

2015-06-13 Thread Karthik Nayak
Rename some of the functions and make them publicly available.
This is a preparatory step for moving code from 'for-each-ref'
to 'ref-filter' to make meaningful, targeted services available to
other commands via public APIs.

Functions renamed are:
parse_atom()->  parse_ref_filter_atom()
verify_format() ->  verify_ref_format()
get_value() ->  get_ref_atom_value()
grab_single_ref()   ->  ref_filter_handler()
sort_refs() ->  ref_array_sort()
show_ref()  ->  show_ref_array_item()
default_sort()  ->  ref_default_sorting()
opt_parse_sort()->  parse_opt_ref_sorting()
cmp_ref_sort()  ->  cmp_ref_sorting()

Rename 'struct ref_sort' to 'struct ref_sorting' in this context.

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

diff --git a/builtin/for-each-ref.c b/builtin/for-each-ref.c
index bb83f7a..5700b25 100644
--- a/builtin/for-each-ref.c
+++ b/builtin/for-each-ref.c
@@ -113,7 +113,7 @@ static int need_color_reset_at_eol;
 /*
  * Used to parse format string and sort specifiers
  */
-static int parse_atom(const char *atom, const char *ep)
+int parse_ref_filter_atom(const char *atom, const char *ep)
 {
const char *sp;
int i, at;
@@ -190,7 +190,7 @@ static const char *find_next(const char *cp)
  * Make sure the format string is well formed, and parse out
  * the used atoms.
  */
-static int verify_format(const char *format)
+int verify_ref_format(const char *format)
 {
const char *cp, *sp;
 
@@ -202,7 +202,7 @@ static int verify_format(const char *format)
if (!ep)
return error("malformed format string %s", sp);
/* sp points at "%(" and ep points at the closing ")" */
-   at = parse_atom(sp + 2, ep);
+   at = parse_ref_filter_atom(sp + 2, ep);
cp = ep + 1;
 
if (skip_prefix(used_atom[at], "color:", &color))
@@ -409,7 +409,7 @@ static void grab_date(const char *buf, struct atom_value 
*v, const char *atomnam
/*
 * We got here because atomname ends in "date" or "date";
 * it's not possible that  is not ":" because
-* parse_atom() wouldn't have allowed it, so we can assume that no
+* parse_ref_filter_atom() wouldn't have allowed it, so we can assume 
that no
 * ":" means no format is specified, and use the default.
 */
formatp = strchr(atomname, ':');
@@ -849,7 +849,7 @@ static void populate_value(struct ref_array_item *ref)
  * Given a ref, return the value for the atom.  This lazily gets value
  * out of the object by calling populate value.
  */
-static void get_value(struct ref_array_item *ref, int atom, struct atom_value 
**v)
+static void get_ref_atom_value(struct ref_array_item *ref, int atom, struct 
atom_value **v)
 {
if (!ref->value) {
populate_value(ref);
@@ -900,8 +900,7 @@ static struct ref_array_item *new_ref_array_item(const char 
*refname,
  * A call-back given to for_each_ref().  Filter refs and keep them for
  * later object processing.
  */
-static int grab_single_ref(const char *refname, const struct object_id *oid,
-  int flag, void *cb_data)
+int ref_filter_handler(const char *refname, const struct object_id *oid, int 
flag, void *cb_data)
 {
struct ref_filter_cbdata *ref_cbdata = cb_data;
struct ref_filter *filter = &ref_cbdata->filter;
@@ -947,14 +946,14 @@ void ref_array_clear(struct ref_array *array)
array->nr = array->alloc = 0;
 }
 
-static int cmp_ref_sort(struct ref_sort *s, struct ref_array_item *a, struct 
ref_array_item *b)
+static int cmp_ref_sorting(struct ref_sorting *s, struct ref_array_item *a, 
struct ref_array_item *b)
 {
struct atom_value *va, *vb;
int cmp;
cmp_type cmp_type = used_atom_type[s->atom];
 
-   get_value(a, s->atom, &va);
-   get_value(b, s->atom, &vb);
+   get_ref_atom_value(a, s->atom, &va);
+   get_ref_atom_value(b, s->atom, &vb);
switch (cmp_type) {
case FIELD_STR:
cmp = strcmp(va->s, vb->s);
@@ -971,24 +970,24 @@ static int cmp_ref_sort(struct ref_sort *s, struct 
ref_array_item *a, struct ref
return (s->reverse) ? -cmp : cmp;
 }
 
-static struct ref_sort *ref_sort;
+static struct ref_sorting *ref_sorting;
 static int compare_refs(const void *a_, const void *b_)
 {
struct ref_array_item *a = *((struct ref_array_item **)a_);
struct ref_array_item *b = *((struct ref_array_item **)b_);
-   struct ref_sort *s;
+   struct ref_sorting *s;
 
-   for (s = ref_sort; s; s = s->next) {
-   int cmp = cmp_ref_sort(s, a, b);
+   for (s = ref_sorting; s; s = s->next) {
+

[PATCH v8 01/11] for-each-ref: extract helper functions out of grab_single_ref()

2015-06-13 Thread Karthik Nayak
Extract two helper functions out of grab_single_ref(). Firstly,
new_refinfo() which is used to allocate memory for a new refinfo
structure and copy the objectname, refname and flag to it.
Secondly, match_name_as_path() which when given an array of patterns
and the refname checks if the refname matches any of the patterns
given while the pattern is a pathname, also supports wildcard
characters.

This is a preperatory patch for restructuring 'for-each-ref' and
eventually moving most of it to 'ref-filter' to provide the
functionality to similar commands via public API's.

Helped-by: Junio C Hamano 
Mentored-by: Christian Couder 
Mentored-by: Matthieu Moy 
Signed-off-by: Karthik Nayak 
---
 builtin/for-each-ref.c | 64 --
 1 file changed, 41 insertions(+), 23 deletions(-)

diff --git a/builtin/for-each-ref.c b/builtin/for-each-ref.c
index f7e51a7..cc65620 100644
--- a/builtin/for-each-ref.c
+++ b/builtin/for-each-ref.c
@@ -851,6 +851,44 @@ struct grab_ref_cbdata {
 };
 
 /*
+ * 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).
+ */
+static int match_name_as_path(const char **pattern, const char *refname)
+{
+   int namelen = strlen(refname);
+   for (; *pattern; pattern++) {
+   const char *p = *pattern;
+   int plen = strlen(p);
+
+   if ((plen <= namelen) &&
+   !strncmp(refname, p, plen) &&
+   (refname[plen] == '\0' ||
+refname[plen] == '/' ||
+p[plen-1] == '/'))
+   return 1;
+   if (!wildmatch(p, refname, WM_PATHNAME, NULL))
+   return 1;
+   }
+   return 0;
+}
+
+/* Allocate space for a new refinfo and copy the objectname and flag to it */
+static struct refinfo *new_refinfo(const char *refname,
+  const unsigned char *objectname,
+  int flag)
+{
+   struct refinfo *ref = xcalloc(1, sizeof(struct refinfo));
+   ref->refname = xstrdup(refname);
+   hashcpy(ref->objectname, objectname);
+   ref->flag = flag;
+
+   return ref;
+}
+
+/*
  * A call-back given to for_each_ref().  Filter refs and keep them for
  * later object processing.
  */
@@ -866,35 +904,15 @@ static int grab_single_ref(const char *refname, const 
struct object_id *oid,
  return 0;
}
 
-   if (*cb->grab_pattern) {
-   const char **pattern;
-   int namelen = strlen(refname);
-   for (pattern = cb->grab_pattern; *pattern; pattern++) {
-   const char *p = *pattern;
-   int plen = strlen(p);
-
-   if ((plen <= namelen) &&
-   !strncmp(refname, p, plen) &&
-   (refname[plen] == '\0' ||
-refname[plen] == '/' ||
-p[plen-1] == '/'))
-   break;
-   if (!wildmatch(p, refname, WM_PATHNAME, NULL))
-   break;
-   }
-   if (!*pattern)
-   return 0;
-   }
+   if (*cb->grab_pattern && !match_name_as_path(cb->grab_pattern, refname))
+   return 0;
 
/*
 * We do not open the object yet; sort may only need refname
 * to do its job and the resulting list may yet to be pruned
 * by maxcount logic.
 */
-   ref = xcalloc(1, sizeof(*ref));
-   ref->refname = xstrdup(refname);
-   hashcpy(ref->objectname, oid->hash);
-   ref->flag = flag;
+   ref = new_refinfo(refname, oid->hash, flag);
 
cnt = cb->grab_cnt;
REALLOC_ARRAY(cb->grab_array, cnt + 1);
-- 
2.4.3.435.g2403634.dirty

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


[PATCH v8 02/11] for-each-ref: clean up code

2015-06-13 Thread Karthik Nayak
In 'grab_single_ref()' remove the extra count variable 'cnt' and
use the variable 'grab_cnt' of structure 'grab_ref_cbdata' directly
instead.

Mentored-by: Christian Couder 
Mentored-by: Matthieu Moy 
Signed-off-by: Karthik Nayak 
---
 builtin/for-each-ref.c | 7 ++-
 1 file changed, 2 insertions(+), 5 deletions(-)

diff --git a/builtin/for-each-ref.c b/builtin/for-each-ref.c
index cc65620..f0d7d44 100644
--- a/builtin/for-each-ref.c
+++ b/builtin/for-each-ref.c
@@ -897,7 +897,6 @@ static int grab_single_ref(const char *refname, const 
struct object_id *oid,
 {
struct grab_ref_cbdata *cb = cb_data;
struct refinfo *ref;
-   int cnt;
 
if (flag & REF_BAD_NAME) {
  warning("ignoring ref with broken name %s", refname);
@@ -914,10 +913,8 @@ static int grab_single_ref(const char *refname, const 
struct object_id *oid,
 */
ref = new_refinfo(refname, oid->hash, flag);
 
-   cnt = cb->grab_cnt;
-   REALLOC_ARRAY(cb->grab_array, cnt + 1);
-   cb->grab_array[cnt++] = ref;
-   cb->grab_cnt = cnt;
+   REALLOC_ARRAY(cb->grab_array, cb->grab_cnt + 1);
+   cb->grab_array[cb->grab_cnt++] = ref;
return 0;
 }
 
-- 
2.4.3.435.g2403634.dirty

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


[PATCH v8 0/11] Create ref-filter from for-each-ref

2015-06-13 Thread karthik nayak
The previous version of the patch can be found at :
http://thread.gmane.org/gmane.comp.version-control.git/271423

Changes :
* Removed an unnecessary commit (v7 3/12)
* Change a comment in 01/11 (v8)

Total changes :

 Makefile   |1 +
 builtin/for-each-ref.c | 1108
+++---
 ref-filter.c   | 1101
+
 ref-filter.h   |   74 
 4 files changed, 1195 insertions(+), 1089 deletions(-)

-- 
Regards,
Karthik Nayak
--
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


Failed assertion in pathspec.c

2015-06-13 Thread Sami Boukortt
Hi,

I can reliably trigger a failed assertion in Git 2.4.3 by performing
the following steps:

mkdir a; cd a
git init
touch a.txt
git add a.txt
git commit -m 'a'
cd ..

mkdir b; cd b
git init
git submodule add ../a
cd a
rm -fr .git
git add .

This results in:
git: pathspec.c:317: prefix_pathspec: Assertion `item->nowildcard_len
<= item->len && item->prefix <= item->len' failed.
--
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 v5] git-rebase--interactive.sh: add config option for custom instruction format

2015-06-13 Thread Michael Rappazzo
Difference between v4 and v5 of this patch:

  - added documention in Documentation/config.txt
  - renamed the new auto-rebase w/ config test to be less inaccurate

Apologies for this, I should have caught these before.


Michael Rappazzo (1):
  git-rebase--interactive.sh: add config option for custom instruction
format

 Documentation/config.txt |  5 +
 Documentation/git-rebase.txt |  7 +++
 git-rebase--interactive.sh   | 20 +---
 t/t3415-rebase-autosquash.sh | 21 +
 4 files changed, 50 insertions(+), 3 deletions(-)

-- 
2.4.2

--
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 v5] git-rebase--interactive.sh: add config option for custom instruction format

2015-06-13 Thread Michael Rappazzo
A config option 'rebase.instructionFormat' can override the
default 'oneline' format of the rebase instruction list.

Since the list is parsed using the left, right or boundary mark plus
the sha1, they are prepended to the instruction format.

Signed-off-by: Michael Rappazzo 
---
 Documentation/config.txt |  5 +
 Documentation/git-rebase.txt |  7 +++
 git-rebase--interactive.sh   | 20 +---
 t/t3415-rebase-autosquash.sh | 21 +
 4 files changed, 50 insertions(+), 3 deletions(-)

diff --git a/Documentation/config.txt b/Documentation/config.txt
index 43bb53c..4c271c6 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -2161,6 +2161,11 @@ rebase.autoStash::
successful rebase might result in non-trivial conflicts.
Defaults to false.
 
+rebase.instructionFormat
+   A format string, as specified in linkgit:git-log[1], to be used for 
+   the instruction list during an interactive rebase.  The format will 
automatically
+   have the long commit hash prepended to the format.  
+
 receive.advertiseAtomic::
By default, git-receive-pack will advertise the atomic push
capability to its clients. If you don't want to this capability
diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt
index 1d01baa..8ddab77 100644
--- a/Documentation/git-rebase.txt
+++ b/Documentation/git-rebase.txt
@@ -213,6 +213,9 @@ rebase.autoSquash::
 rebase.autoStash::
If set to true enable '--autostash' option by default.
 
+rebase.instructionFormat::
+   Custom commit list format to use during an '--interactive' rebase.
+
 OPTIONS
 ---
 --onto ::
@@ -359,6 +362,10 @@ default is `--no-fork-point`, otherwise the default is 
`--fork-point`.
Make a list of the commits which are about to be rebased.  Let the
user edit that list before rebasing.  This mode can also be used to
split commits (see SPLITTING COMMITS below).
++
+The commit list format can be changed by setting the configuration option
+rebase.instructionFormat.  A customized instruction format will automatically
+have the long commit hash prepended to the format.
 
 -p::
 --preserve-merges::
diff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh
index dc3133f..755f9c1 100644
--- a/git-rebase--interactive.sh
+++ b/git-rebase--interactive.sh
@@ -740,10 +740,15 @@ collapse_todo_ids() {
 # "pick sha1 fixup!/squash! msg" appears in it so that the latter
 # comes immediately after the former, and change "pick" to
 # "fixup"/"squash".
+#
+# Note that if the config has specified a custom instruction format
+# each log message will be re-retrieved in order to normalize the 
+# autosquash arrangement
 rearrange_squash () {
# extract fixup!/squash! lines and resolve any referenced sha1's
while read -r pick sha1 message
do
+   test -z "${format}" || message=$(git log -n 1 --format="%s" 
${sha1})
case "$message" in
"squash! "*|"fixup! "*)
action="${message%%!*}"
@@ -785,6 +790,7 @@ rearrange_squash () {
*" $sha1 "*) continue ;;
esac
printf '%s\n' "$pick $sha1 $message"
+   test -z "${format}" || message=$(git log -n 1 --format="%s" 
${sha1})
used="$used$sha1 "
while read -r squash action msg_prefix msg_content
do
@@ -802,8 +808,13 @@ rearrange_squash () {
case "$message" in "$msg_content"*) emit=1;; 
esac ;;
esac
if test $emit = 1; then
-   real_prefix=$(echo "$msg_prefix" | sed "s/,/! 
/g")
-   printf '%s\n' "$action $squash 
${real_prefix}$msg_content"
+   if test -n "${format}"
+   then
+   msg_content=$(git log -n 1 
--format="${format}" ${squash})
+   else
+   msg_content="$(echo "$msg_prefix" | sed 
"s/,/! /g")$msg_content"
+   fi
+   printf '%s\n' "$action $squash $msg_content"
used="$used$squash "
fi
done <"$1.sq"
@@ -977,7 +988,10 @@ else
revisions=$onto...$orig_head
shortrevisions=$shorthead
 fi
-git rev-list $merges_option --pretty=oneline --reverse --left-right 
--topo-order \
+format=$(git config --get rebase.instructionFormat)
+# the 'rev-list .. | sed' requires %m to parse; the instruction requires %H to 
parse
+git rev-list $merges_option --format="%m%H ${format:-%s}" \
+   --reverse --left-right --topo-order \
$revisions ${restrict_revision+^$restrict_revision} | \
sed -n "s/^>//p" |
 while read -r sha1 rest
diff --git a/t/t3415-rebase-autosquash.sh b/t/t3415-rebase

Re: [PATCH 0/8] object_id part 2

2015-06-13 Thread brian m. carlson
On Sat, Jun 13, 2015 at 10:45:29AM +0200, Michael Haggerty wrote:
> In the same email where I made those design suggestions, I also I
> pointed out a bug in the implementation of parse_oid_hex(). Maybe that
> is the reason for the test failures.

It probably is, although I either botched a conversion in the branch I'm
working on as well, or the area for that code is lacking tests, since I
don't think the tests are failing there.  In the latter case, I'll send
a testsuite patch as part of my next series.
-- 
brian m. carlson / brian with sandals: Houston, Texas, US
+1 832 623 2791 | http://www.crustytoothpaste.net/~bmc | My opinion only
OpenPGP: RSA v4 4096b: 88AC E9B2 9196 305B A994 7552 F1BA 225C 0223 B187


signature.asc
Description: Digital signature


[PATCH v2 08/12] initial_ref_transaction_commit(): function for initial ref creation

2015-06-13 Thread Michael Haggerty
"git clone" uses shortcuts when creating the initial set of
references:

* It writes them directly to packed-refs.

* It doesn't lock the individual references (though it does lock the
  packed-refs file).

* It doesn't check for refname conflicts between two new references or
  between one new reference and any hypothetical old ones.

* It doesn't create reflog entries for the reference creations.

This functionality was implemented in builtin/clone.c. But really that
file shouldn't have such intimate knowledge of how references are
stored. So provide a new function in the refs API,
initial_ref_transaction_commit(), which can be used for initial
reference creation. The new function is based on the ref_transaction
interface.

This means that we can make some other functions private to the refs
module. That will be done in a followup commit.

It would seem to make sense to add a test here that there are no
existing references, because that is how the function *should* be
used. But in fact, the "testgit" remote helper appears to call it
*after* having set up refs/remotes//HEAD and
refs/remotes//master, so we can't be so strict. For now, the
function trusts its caller to only call it when it makes sense. Future
commits will add some more limited sanity checks.

Signed-off-by: Michael Haggerty 
---
 builtin/clone.c | 19 +++
 refs.c  | 47 +++
 refs.h  | 14 ++
 3 files changed, 76 insertions(+), 4 deletions(-)

diff --git a/builtin/clone.c b/builtin/clone.c
index b878252..bd2a50a 100644
--- a/builtin/clone.c
+++ b/builtin/clone.c
@@ -500,16 +500,27 @@ static void write_remote_refs(const struct ref 
*local_refs)
 {
const struct ref *r;
 
-   lock_packed_refs(LOCK_DIE_ON_ERROR);
+   struct ref_transaction *t;
+   struct strbuf err = STRBUF_INIT;
+
+   t = ref_transaction_begin(&err);
+   if (!t)
+   die(err.buf);
 
for (r = local_refs; r; r = r->next) {
if (!r->peer_ref)
continue;
-   add_packed_ref(r->peer_ref->name, r->old_sha1);
+   if (ref_transaction_create(t, r->peer_ref->name, r->old_sha1,
+  0, NULL, &err))
+   die(err.buf);
+   }
+
+   if (initial_ref_transaction_commit(t, &err)) {
+   die(err.buf);
}
 
-   if (commit_packed_refs())
-   die_errno("unable to overwrite old ref-pack file");
+   strbuf_release(&err);
+   ref_transaction_free(t);
 }
 
 static void write_followtags(const struct ref *refs, const char *msg)
diff --git a/refs.c b/refs.c
index 832d628..05e5d42 100644
--- a/refs.c
+++ b/refs.c
@@ -4045,6 +4045,53 @@ cleanup:
return ret;
 }
 
+int initial_ref_transaction_commit(struct ref_transaction *transaction,
+  struct strbuf *err)
+{
+   int ret = 0, i;
+   int n = transaction->nr;
+   struct ref_update **updates = transaction->updates;
+
+   assert(err);
+
+   if (transaction->state != REF_TRANSACTION_OPEN)
+   die("BUG: commit called for transaction that is not open");
+
+   for (i = 0; i < n; i++) {
+   struct ref_update *update = updates[i];
+
+   if ((update->flags & REF_HAVE_OLD) &&
+   !is_null_sha1(update->old_sha1))
+   die("BUG: initial ref transaction with old_sha1 set");
+   }
+
+   if (lock_packed_refs(0)) {
+   strbuf_addf(err, "unable to lock packed-refs file: %s",
+   strerror(errno));
+   ret = TRANSACTION_GENERIC_ERROR;
+   goto cleanup;
+   }
+
+   for (i = 0; i < n; i++) {
+   struct ref_update *update = updates[i];
+
+   if ((update->flags & REF_HAVE_NEW) &&
+   !is_null_sha1(update->new_sha1))
+   add_packed_ref(update->refname, update->new_sha1);
+   }
+
+   if (commit_packed_refs()) {
+   strbuf_addf(err, "unable to commit packed-refs file: %s",
+   strerror(errno));
+   ret = TRANSACTION_GENERIC_ERROR;
+   goto cleanup;
+   }
+
+cleanup:
+   transaction->state = REF_TRANSACTION_CLOSED;
+   return ret;
+}
+
 char *shorten_unambiguous_ref(const char *refname, int strict)
 {
int i;
diff --git a/refs.h b/refs.h
index 5f3bea7..9602889 100644
--- a/refs.h
+++ b/refs.h
@@ -366,6 +366,20 @@ int ref_transaction_commit(struct ref_transaction 
*transaction,
   struct strbuf *err);
 
 /*
+ * Like ref_transaction_commit(), but optimized for creating
+ * references when originally initializing a repository (e.g., by "git
+ * clone"). It writes the new references directly to packed-refs
+ * without locking the individual references.
+ *
+ * It is a bug to call this function when there might be other
+ 

[PATCH v2 07/12] repack_without_refs(): make function private

2015-06-13 Thread Michael Haggerty
It is no longer called from outside of the refs module. Also move its
docstring and change it to imperative voice.

Signed-off-by: Michael Haggerty 
---
 refs.c |  9 -
 refs.h | 11 ---
 2 files changed, 8 insertions(+), 12 deletions(-)

diff --git a/refs.c b/refs.c
index 5386077..832d628 100644
--- a/refs.c
+++ b/refs.c
@@ -2724,7 +2724,14 @@ int pack_refs(unsigned int flags)
return 0;
 }
 
-int repack_without_refs(struct string_list *refnames, struct strbuf *err)
+/*
+ * Rewrite the packed-refs file, omitting any refs listed in
+ * 'refnames'. On error, leave packed-refs unchanged, write an error
+ * message to 'err', and return a nonzero value.
+ *
+ * The refs in 'refnames' needn't be sorted. `err` must not be NULL.
+ */
+static int repack_without_refs(struct string_list *refnames, struct strbuf 
*err)
 {
struct ref_dir *packed;
struct string_list_item *refname;
diff --git a/refs.h b/refs.h
index 1a5d44a..5f3bea7 100644
--- a/refs.h
+++ b/refs.h
@@ -154,17 +154,6 @@ extern void rollback_packed_refs(void);
  */
 int pack_refs(unsigned int flags);
 
-/*
- * Rewrite the packed-refs file, omitting any refs listed in
- * 'refnames'. On error, packed-refs will be unchanged, the return
- * value is nonzero, and a message about the error is written to the
- * 'err' strbuf.
- *
- * The refs in 'refnames' needn't be sorted. `err` must not be NULL.
- */
-extern int repack_without_refs(struct string_list *refnames,
-  struct strbuf *err);
-
 extern int ref_exists(const char *);
 
 extern int is_branch(const char *refname);
-- 
2.1.4

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


[PATCH v2 00/12] Improve "refs" module encapsulation

2015-06-13 Thread Michael Haggerty
This is v2 of this patch series. I think I have addressed all of the
feedback from v1 [1]. Thanks to Stefan, Peff and Junio for their
feedback.

Changes since v1:

* Change docstring for delete_ref() and a comment within the function
  definition.

* Squash together two commits dealing with the error message in
  delete_refs().

These patches are also available from my GitHub account [2] as branch
"init-delete-refs-api".

Michael

[1] http://thread.gmane.org/gmane.comp.version-control.git/271017
[2] https://github.com/mhagger/git

Michael Haggerty (12):
  delete_ref(): move declaration to refs.h
  remove_branches(): remove temporary
  delete_ref(): handle special case more explicitly
  delete_refs(): new function for the refs API
  delete_refs(): improve error message
  prune_remote(): use delete_refs()
  repack_without_refs(): make function private
  initial_ref_transaction_commit(): function for initial ref creation
  refs: remove some functions from the module's public interface
  initial_ref_transaction_commit(): check for duplicate refs
  initial_ref_transaction_commit(): check for ref D/F conflicts
  refs: move the remaining ref module declarations to refs.h

 archive.c   |   1 +
 builtin/blame.c |   1 +
 builtin/clone.c |  19 -
 builtin/fast-export.c   |   1 +
 builtin/fmt-merge-msg.c |   1 +
 builtin/init-db.c   |   1 +
 builtin/log.c   |   1 +
 builtin/remote.c|  33 +---
 cache.h |  68 
 refs.c  | 171 ---
 refs.h  | 211 +++-
 remote-testsvn.c|   1 +
 12 files changed, 321 insertions(+), 188 deletions(-)

-- 
2.1.4

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


[PATCH v2 05/12] delete_refs(): improve error message

2015-06-13 Thread Michael Haggerty
Change the error message from

Could not remove branch %s

to

could not remove reference %s

* s/branch/reference/. This change makes sense even for the existing
  caller, which uses the function to delete remote-tracking
  branches.

* Convert it to lower case, as per our usual convention.

Signed-off-by: Michael Haggerty 
---
 refs.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/refs.c b/refs.c
index 6f62bd1..5386077 100644
--- a/refs.c
+++ b/refs.c
@@ -2831,7 +2831,7 @@ int delete_refs(struct string_list *refnames)
const char *refname = refnames->items[i].string;
 
if (delete_ref(refname, NULL, 0))
-   result |= error(_("Could not remove branch %s"), 
refname);
+   result |= error(_("could not remove reference %s"), 
refname);
}
 
return result;
-- 
2.1.4

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


[PATCH v2 02/12] remove_branches(): remove temporary

2015-06-13 Thread Michael Haggerty
Signed-off-by: Michael Haggerty 
---
 builtin/remote.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/builtin/remote.c b/builtin/remote.c
index f4a6ec9..53b8e13 100644
--- a/builtin/remote.c
+++ b/builtin/remote.c
@@ -756,8 +756,7 @@ static int remove_branches(struct string_list *branches)
strbuf_release(&err);
 
for (i = 0; i < branches->nr; i++) {
-   struct string_list_item *item = branches->items + i;
-   const char *refname = item->string;
+   const char *refname = branches->items[i].string;
 
if (delete_ref(refname, NULL, 0))
result |= error(_("Could not remove branch %s"), 
refname);
-- 
2.1.4

--
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 09/12] refs: remove some functions from the module's public interface

2015-06-13 Thread Michael Haggerty
The following functions are no longer used from outside the refs
module:

* lock_packed_refs()
* add_packed_ref()
* commit_packed_refs()
* rollback_packed_refs()

So make these functions private.

This is an important step, because it means that nobody outside of the
refs module needs to know the difference between loose and packed
references.

Signed-off-by: Michael Haggerty 
---
 refs.c | 31 ---
 refs.h | 30 --
 2 files changed, 24 insertions(+), 37 deletions(-)

diff --git a/refs.c b/refs.c
index 05e5d42..a715524 100644
--- a/refs.c
+++ b/refs.c
@@ -1314,7 +1314,13 @@ static struct ref_dir *get_packed_refs(struct ref_cache 
*refs)
return get_packed_ref_dir(get_packed_ref_cache(refs));
 }
 
-void add_packed_ref(const char *refname, const unsigned char *sha1)
+/*
+ * Add a reference to the in-memory packed reference cache.  This may
+ * only be called while the packed-refs file is locked (see
+ * lock_packed_refs()).  To actually write the packed-refs file, call
+ * commit_packed_refs().
+ */
+static void add_packed_ref(const char *refname, const unsigned char *sha1)
 {
struct packed_ref_cache *packed_ref_cache =
get_packed_ref_cache(&ref_cache);
@@ -2503,8 +2509,12 @@ static int write_packed_entry_fn(struct ref_entry 
*entry, void *cb_data)
return 0;
 }
 
-/* This should return a meaningful errno on failure */
-int lock_packed_refs(int flags)
+/*
+ * Lock the packed-refs file for writing. Flags is passed to
+ * hold_lock_file_for_update(). Return 0 on success. On errors, set
+ * errno appropriately and return a nonzero value.
+ */
+static int lock_packed_refs(int flags)
 {
static int timeout_configured = 0;
static int timeout_value = 1000;
@@ -2534,10 +2544,12 @@ int lock_packed_refs(int flags)
 }
 
 /*
- * Commit the packed refs changes.
- * On error we must make sure that errno contains a meaningful value.
+ * Write the current version of the packed refs cache from memory to
+ * disk. The packed-refs file must already be locked for writing (see
+ * lock_packed_refs()). Return zero on success. On errors, set errno
+ * and return a nonzero value
  */
-int commit_packed_refs(void)
+static int commit_packed_refs(void)
 {
struct packed_ref_cache *packed_ref_cache =
get_packed_ref_cache(&ref_cache);
@@ -2566,7 +2578,12 @@ int commit_packed_refs(void)
return error;
 }
 
-void rollback_packed_refs(void)
+/*
+ * Rollback the lockfile for the packed-refs file, and discard the
+ * in-memory packed reference cache.  (The packed-refs file will be
+ * read anew if it is needed again after this function is called.)
+ */
+static void rollback_packed_refs(void)
 {
struct packed_ref_cache *packed_ref_cache =
get_packed_ref_cache(&ref_cache);
diff --git a/refs.h b/refs.h
index 9602889..cd87f2f 100644
--- a/refs.h
+++ b/refs.h
@@ -111,36 +111,6 @@ extern void warn_dangling_symref(FILE *fp, const char 
*msg_fmt, const char *refn
 extern void warn_dangling_symrefs(FILE *fp, const char *msg_fmt, const struct 
string_list *refnames);
 
 /*
- * Lock the packed-refs file for writing.  Flags is passed to
- * hold_lock_file_for_update().  Return 0 on success.
- * Errno is set to something meaningful on error.
- */
-extern int lock_packed_refs(int flags);
-
-/*
- * Add a reference to the in-memory packed reference cache.  This may
- * only be called while the packed-refs file is locked (see
- * lock_packed_refs()).  To actually write the packed-refs file, call
- * commit_packed_refs().
- */
-extern void add_packed_ref(const char *refname, const unsigned char *sha1);
-
-/*
- * Write the current version of the packed refs cache from memory to
- * disk.  The packed-refs file must already be locked for writing (see
- * lock_packed_refs()).  Return zero on success.
- * Sets errno to something meaningful on error.
- */
-extern int commit_packed_refs(void);
-
-/*
- * Rollback the lockfile for the packed-refs file, and discard the
- * in-memory packed reference cache.  (The packed-refs file will be
- * read anew if it is needed again after this function is called.)
- */
-extern void rollback_packed_refs(void);
-
-/*
  * Flags for controlling behaviour of pack_refs()
  * PACK_REFS_PRUNE: Prune loose refs after packing
  * PACK_REFS_ALL:   Pack _all_ refs, not just tags and already packed refs
-- 
2.1.4

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


[PATCH v2 10/12] initial_ref_transaction_commit(): check for duplicate refs

2015-06-13 Thread Michael Haggerty
Error out if the ref_transaction includes more than one update for any
refname.

Signed-off-by: Michael Haggerty 
---
 refs.c | 11 +++
 1 file changed, 11 insertions(+)

diff --git a/refs.c b/refs.c
index a715524..dfe9090 100644
--- a/refs.c
+++ b/refs.c
@@ -4068,12 +4068,22 @@ int initial_ref_transaction_commit(struct 
ref_transaction *transaction,
int ret = 0, i;
int n = transaction->nr;
struct ref_update **updates = transaction->updates;
+   struct string_list affected_refnames = STRING_LIST_INIT_NODUP;
 
assert(err);
 
if (transaction->state != REF_TRANSACTION_OPEN)
die("BUG: commit called for transaction that is not open");
 
+   /* Fail if a refname appears more than once in the transaction: */
+   for (i = 0; i < n; i++)
+   string_list_append(&affected_refnames, updates[i]->refname);
+   string_list_sort(&affected_refnames);
+   if (ref_update_reject_duplicates(&affected_refnames, err)) {
+   ret = TRANSACTION_GENERIC_ERROR;
+   goto cleanup;
+   }
+
for (i = 0; i < n; i++) {
struct ref_update *update = updates[i];
 
@@ -4106,6 +4116,7 @@ int initial_ref_transaction_commit(struct ref_transaction 
*transaction,
 
 cleanup:
transaction->state = REF_TRANSACTION_CLOSED;
+   string_list_clear(&affected_refnames, 0);
return ret;
 }
 
-- 
2.1.4

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


[PATCH v2 12/12] refs: move the remaining ref module declarations to refs.h

2015-06-13 Thread Michael Haggerty
Some functions from the refs module were still declared in cache.h.
Move them to refs.h.

Add some parameter names where they were missing.

Signed-off-by: Michael Haggerty 
---
 archive.c   |   1 +
 builtin/blame.c |   1 +
 builtin/fast-export.c   |   1 +
 builtin/fmt-merge-msg.c |   1 +
 builtin/init-db.c   |   1 +
 builtin/log.c   |   1 +
 cache.h |  66 ---
 refs.c  |   6 ++-
 refs.h  | 139 +---
 remote-testsvn.c|   1 +
 10 files changed, 118 insertions(+), 100 deletions(-)

diff --git a/archive.c b/archive.c
index d37c41d..936a594 100644
--- a/archive.c
+++ b/archive.c
@@ -1,4 +1,5 @@
 #include "cache.h"
+#include "refs.h"
 #include "commit.h"
 #include "tree-walk.h"
 #include "attr.h"
diff --git a/builtin/blame.c b/builtin/blame.c
index b3e948e..1c998cb 100644
--- a/builtin/blame.c
+++ b/builtin/blame.c
@@ -6,6 +6,7 @@
  */
 
 #include "cache.h"
+#include "refs.h"
 #include "builtin.h"
 #include "blob.h"
 #include "commit.h"
diff --git a/builtin/fast-export.c b/builtin/fast-export.c
index b8182c2..d23f3be 100644
--- a/builtin/fast-export.c
+++ b/builtin/fast-export.c
@@ -5,6 +5,7 @@
  */
 #include "builtin.h"
 #include "cache.h"
+#include "refs.h"
 #include "commit.h"
 #include "object.h"
 #include "tag.h"
diff --git a/builtin/fmt-merge-msg.c b/builtin/fmt-merge-msg.c
index 05f4c26..4ba7f28 100644
--- a/builtin/fmt-merge-msg.c
+++ b/builtin/fmt-merge-msg.c
@@ -1,5 +1,6 @@
 #include "builtin.h"
 #include "cache.h"
+#include "refs.h"
 #include "commit.h"
 #include "diff.h"
 #include "revision.h"
diff --git a/builtin/init-db.c b/builtin/init-db.c
index 4335738..49df78d 100644
--- a/builtin/init-db.c
+++ b/builtin/init-db.c
@@ -4,6 +4,7 @@
  * Copyright (C) Linus Torvalds, 2005
  */
 #include "cache.h"
+#include "refs.h"
 #include "builtin.h"
 #include "exec_cmd.h"
 #include "parse-options.h"
diff --git a/builtin/log.c b/builtin/log.c
index e67671e..3caa917 100644
--- a/builtin/log.c
+++ b/builtin/log.c
@@ -5,6 +5,7 @@
  *  2006 Junio Hamano
  */
 #include "cache.h"
+#include "refs.h"
 #include "color.h"
 #include "commit.h"
 #include "diff.h"
diff --git a/cache.h b/cache.h
index be92121..1c00098 100644
--- a/cache.h
+++ b/cache.h
@@ -1009,76 +1009,10 @@ extern int get_oid_hex(const char *hex, struct 
object_id *sha1);
 
 extern char *sha1_to_hex(const unsigned char *sha1);   /* static buffer 
result! */
 extern char *oid_to_hex(const struct object_id *oid);  /* same static buffer 
as sha1_to_hex */
-extern int read_ref_full(const char *refname, int resolve_flags,
-unsigned char *sha1, int *flags);
-extern int read_ref(const char *refname, unsigned char *sha1);
 
-/*
- * Resolve a reference, recursively following symbolic refererences.
- *
- * Store the referred-to object's name in sha1 and return the name of
- * the non-symbolic reference that ultimately pointed at it.  The
- * return value, if not NULL, is a pointer into either a static buffer
- * or the input ref.
- *
- * If the reference cannot be resolved to an object, the behavior
- * depends on the RESOLVE_REF_READING flag:
- *
- * - If RESOLVE_REF_READING is set, return NULL.
- *
- * - If RESOLVE_REF_READING is not set, clear sha1 and return the name of
- *   the last reference name in the chain, which will either be a non-symbolic
- *   reference or an undefined reference.  If this is a prelude to
- *   "writing" to the ref, the return value is the name of the ref
- *   that will actually be created or changed.
- *
- * If the RESOLVE_REF_NO_RECURSE flag is passed, only resolves one
- * level of symbolic reference.  The value stored in sha1 for a symbolic
- * reference will always be null_sha1 in this case, and the return
- * value is the reference that the symref refers to directly.
- *
- * If flags is non-NULL, set the value that it points to the
- * combination of REF_ISPACKED (if the reference was found among the
- * packed references), REF_ISSYMREF (if the initial reference was a
- * symbolic reference), REF_BAD_NAME (if the reference name is ill
- * formed --- see RESOLVE_REF_ALLOW_BAD_NAME below), and REF_ISBROKEN
- * (if the ref is malformed or has a bad name). See refs.h for more detail
- * on each flag.
- *
- * If ref is not a properly-formatted, normalized reference, return
- * NULL.  If more than MAXDEPTH recursive symbolic lookups are needed,
- * give up and return NULL.
- *
- * RESOLVE_REF_ALLOW_BAD_NAME allows resolving refs even when their
- * name is invalid according to git-check-ref-format(1).  If the name
- * is bad then the value stored in sha1 will be null_sha1 and the two
- * flags REF_ISBROKEN and REF_BAD_NAME will be set.
- *
- * Even with RESOLVE_REF_ALLOW_BAD_NAME, names that escape the refs/
- * directory and do not consist of all caps and underscores cannot be
- * resolved. The function returns NULL for such ref names.
- * Caps and un

[PATCH v2 06/12] prune_remote(): use delete_refs()

2015-06-13 Thread Michael Haggerty
This will result in errors being emitted for references that can't be
deleted, but that is a good thing.

Signed-off-by: Michael Haggerty 
---
 builtin/remote.c | 11 ++-
 1 file changed, 2 insertions(+), 9 deletions(-)

diff --git a/builtin/remote.c b/builtin/remote.c
index c8dc724..cc3c741 100644
--- a/builtin/remote.c
+++ b/builtin/remote.c
@@ -1314,19 +1314,12 @@ static int prune_remote(const char *remote, int dry_run)
string_list_append(&refs_to_prune, item->util);
string_list_sort(&refs_to_prune);
 
-   if (!dry_run) {
-   struct strbuf err = STRBUF_INIT;
-   if (repack_without_refs(&refs_to_prune, &err))
-   result |= error("%s", err.buf);
-   strbuf_release(&err);
-   }
+   if (!dry_run)
+   result |= delete_refs(&refs_to_prune);
 
for_each_string_list_item(item, &states.stale) {
const char *refname = item->util;
 
-   if (!dry_run)
-   result |= delete_ref(refname, NULL, 0);
-
if (dry_run)
printf_ln(_(" * [would prune] %s"),
   abbrev_ref(refname, "refs/remotes/"));
-- 
2.1.4

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


[PATCH v2 11/12] initial_ref_transaction_commit(): check for ref D/F conflicts

2015-06-13 Thread Michael Haggerty
In initial_ref_transaction_commit(), check for D/F conflicts (i.e.,
the type of conflict that exists between "refs/foo" and
"refs/foo/bar") among the references being created and between the
references being created and any hypothetical existing references.

Ideally, there shouldn't *be* any existing references when this
function is called. But, at least in the case of the "testgit" remote
helper, "clone" can be called after the remote-tracking "HEAD" and
"master" branches have already been created. So let's just do the
full-blown check.

Signed-off-by: Michael Haggerty 
---
 refs.c | 34 ++
 1 file changed, 34 insertions(+)

diff --git a/refs.c b/refs.c
index dfe9090..340d67f 100644
--- a/refs.c
+++ b/refs.c
@@ -4062,9 +4062,19 @@ cleanup:
return ret;
 }
 
+static int ref_present(const char *refname,
+  const struct object_id *oid, int flags, void *cb_data)
+{
+   struct string_list *affected_refnames = cb_data;
+
+   return string_list_has_string(affected_refnames, refname);
+}
+
 int initial_ref_transaction_commit(struct ref_transaction *transaction,
   struct strbuf *err)
 {
+   struct ref_dir *loose_refs = get_loose_refs(&ref_cache);
+   struct ref_dir *packed_refs = get_packed_refs(&ref_cache);
int ret = 0, i;
int n = transaction->nr;
struct ref_update **updates = transaction->updates;
@@ -4084,12 +4094,36 @@ int initial_ref_transaction_commit(struct 
ref_transaction *transaction,
goto cleanup;
}
 
+   /*
+* It's really undefined to call this function in an active
+* repository or when there are existing references: we are
+* only locking and changing packed-refs, so (1) any
+* simultaneous processes might try to change a reference at
+* the same time we do, and (2) any existing loose versions of
+* the references that we are setting would have precedence
+* over our values. But some remote helpers create the remote
+* "HEAD" and "master" branches before calling this function,
+* so here we really only check that none of the references
+* that we are creating already exists.
+*/
+   if (for_each_rawref(ref_present, &affected_refnames))
+   die("BUG: initial ref transaction called with existing refs");
+
for (i = 0; i < n; i++) {
struct ref_update *update = updates[i];
 
if ((update->flags & REF_HAVE_OLD) &&
!is_null_sha1(update->old_sha1))
die("BUG: initial ref transaction with old_sha1 set");
+   if (verify_refname_available(update->refname,
+&affected_refnames, NULL,
+loose_refs, err) ||
+   verify_refname_available(update->refname,
+&affected_refnames, NULL,
+packed_refs, err)) {
+   ret = TRANSACTION_NAME_CONFLICT;
+   goto cleanup;
+   }
}
 
if (lock_packed_refs(0)) {
-- 
2.1.4

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


[PATCH v2 01/12] delete_ref(): move declaration to refs.h

2015-06-13 Thread Michael Haggerty
Also

* Add a docstring

* Rename the second parameter to "old_sha1", to be consistent with the
  convention used elsewhere in the refs module

Signed-off-by: Michael Haggerty 
---
 cache.h |  2 --
 refs.c  |  5 +++--
 refs.h  | 10 ++
 3 files changed, 13 insertions(+), 4 deletions(-)

diff --git a/cache.h b/cache.h
index 571c98f..be92121 100644
--- a/cache.h
+++ b/cache.h
@@ -585,8 +585,6 @@ extern void update_index_if_able(struct index_state *, 
struct lock_file *);
 extern int hold_locked_index(struct lock_file *, int);
 extern void set_alternate_index_output(const char *);
 
-extern int delete_ref(const char *, const unsigned char *sha1, unsigned int 
flags);
-
 /* Environment bits from configuration mechanism */
 extern int trust_executable_bit;
 extern int trust_ctime;
diff --git a/refs.c b/refs.c
index a742d79..b575bb8 100644
--- a/refs.c
+++ b/refs.c
@@ -2789,7 +2789,8 @@ static int delete_ref_loose(struct ref_lock *lock, int 
flag, struct strbuf *err)
return 0;
 }
 
-int delete_ref(const char *refname, const unsigned char *sha1, unsigned int 
flags)
+int delete_ref(const char *refname, const unsigned char *old_sha1,
+  unsigned int flags)
 {
struct ref_transaction *transaction;
struct strbuf err = STRBUF_INIT;
@@ -2797,7 +2798,7 @@ int delete_ref(const char *refname, const unsigned char 
*sha1, unsigned int flag
transaction = ref_transaction_begin(&err);
if (!transaction ||
ref_transaction_delete(transaction, refname,
-  (sha1 && !is_null_sha1(sha1)) ? sha1 : NULL,
+  (old_sha1 && !is_null_sha1(old_sha1)) ? 
old_sha1 : NULL,
   flags, NULL, &err) ||
ref_transaction_commit(transaction, &err)) {
error("%s", err.buf);
diff --git a/refs.h b/refs.h
index 8c3d433..68b5e81 100644
--- a/refs.h
+++ b/refs.h
@@ -202,6 +202,16 @@ extern int read_ref_at(const char *refname, unsigned int 
flags,
 /** Check if a particular reflog exists */
 extern int reflog_exists(const char *refname);
 
+/*
+ * Delete the specified reference. If old_sha1 is non-NULL and not
+ * NULL_SHA1, then verify that the current value of the reference is
+ * old_sha1 before deleting it. If old_sha1 is NULL or NULL_SHA1,
+ * delete the reference if it exists, regardless of its old value.
+ * flags is passed through to ref_transaction_delete().
+ */
+extern int delete_ref(const char *refname, const unsigned char *old_sha1,
+ unsigned int flags);
+
 /** Delete a reflog */
 extern int delete_reflog(const char *refname);
 
-- 
2.1.4

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


[PATCH v2 04/12] delete_refs(): new function for the refs API

2015-06-13 Thread Michael Haggerty
Move the function remove_branches() from builtin/remote.c to refs.c,
rename it to delete_refs(), and make it public.

Signed-off-by: Michael Haggerty 
---
 builtin/remote.c | 21 +
 refs.c   | 19 +++
 refs.h   |  7 +++
 3 files changed, 27 insertions(+), 20 deletions(-)

diff --git a/builtin/remote.c b/builtin/remote.c
index 53b8e13..c8dc724 100644
--- a/builtin/remote.c
+++ b/builtin/remote.c
@@ -746,25 +746,6 @@ static int mv(int argc, const char **argv)
return 0;
 }
 
-static int remove_branches(struct string_list *branches)
-{
-   struct strbuf err = STRBUF_INIT;
-   int i, result = 0;
-
-   if (repack_without_refs(branches, &err))
-   result |= error("%s", err.buf);
-   strbuf_release(&err);
-
-   for (i = 0; i < branches->nr; i++) {
-   const char *refname = branches->items[i].string;
-
-   if (delete_ref(refname, NULL, 0))
-   result |= error(_("Could not remove branch %s"), 
refname);
-   }
-
-   return result;
-}
-
 static int rm(int argc, const char **argv)
 {
struct option options[] = {
@@ -821,7 +802,7 @@ static int rm(int argc, const char **argv)
strbuf_release(&buf);
 
if (!result)
-   result = remove_branches(&branches);
+   result = delete_refs(&branches);
string_list_clear(&branches, 0);
 
if (skipped.nr) {
diff --git a/refs.c b/refs.c
index f0b6cec..6f62bd1 100644
--- a/refs.c
+++ b/refs.c
@@ -2818,6 +2818,25 @@ int delete_ref(const char *refname, const unsigned char 
*old_sha1,
return 0;
 }
 
+int delete_refs(struct string_list *refnames)
+{
+   struct strbuf err = STRBUF_INIT;
+   int i, result = 0;
+
+   if (repack_without_refs(refnames, &err))
+   result |= error("%s", err.buf);
+   strbuf_release(&err);
+
+   for (i = 0; i < refnames->nr; i++) {
+   const char *refname = refnames->items[i].string;
+
+   if (delete_ref(refname, NULL, 0))
+   result |= error(_("Could not remove branch %s"), 
refname);
+   }
+
+   return result;
+}
+
 /*
  * People using contrib's git-new-workdir have .git/logs/refs ->
  * /some/other/path/.git/logs/refs, and that may live on another device.
diff --git a/refs.h b/refs.h
index 68b5e81..1a5d44a 100644
--- a/refs.h
+++ b/refs.h
@@ -212,6 +212,13 @@ extern int reflog_exists(const char *refname);
 extern int delete_ref(const char *refname, const unsigned char *old_sha1,
  unsigned int flags);
 
+/*
+ * Delete the specified references. If there are any problems, emit
+ * errors but attempt to keep going (i.e., the deletes are not done in
+ * an all-or-nothing transaction).
+ */
+extern int delete_refs(struct string_list *refnames);
+
 /** Delete a reflog */
 extern int delete_reflog(const char *refname);
 
-- 
2.1.4

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


[PATCH v2 03/12] delete_ref(): handle special case more explicitly

2015-06-13 Thread Michael Haggerty
delete_ref() uses a different convention for its old_sha1 parameter
than, say, ref_transaction_delete(): NULL_SHA1 means not to check the
old value. Make this fact a little bit clearer in the code by handling
it in explicit, commented code rather than burying it in a conditional
expression.

Signed-off-by: Michael Haggerty 
---
 refs.c | 11 +--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/refs.c b/refs.c
index b575bb8..f0b6cec 100644
--- a/refs.c
+++ b/refs.c
@@ -2795,10 +2795,17 @@ int delete_ref(const char *refname, const unsigned char 
*old_sha1,
struct ref_transaction *transaction;
struct strbuf err = STRBUF_INIT;
 
+   /*
+* Treat NULL_SHA1 and NULL alike, to mean "we don't care what
+* the old value of the reference was (or even if it didn't
+* exist)":
+*/
+   if (old_sha1 && is_null_sha1(old_sha1))
+   old_sha1 = NULL;
+
transaction = ref_transaction_begin(&err);
if (!transaction ||
-   ref_transaction_delete(transaction, refname,
-  (old_sha1 && !is_null_sha1(old_sha1)) ? 
old_sha1 : NULL,
+   ref_transaction_delete(transaction, refname, old_sha1,
   flags, NULL, &err) ||
ref_transaction_commit(transaction, &err)) {
error("%s", err.buf);
-- 
2.1.4

--
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 01/13] delete_ref(): move declaration to refs.h

2015-06-13 Thread Michael Haggerty
On 06/09/2015 06:42 PM, Stefan Beller wrote:
> On Tue, Jun 9, 2015 at 3:10 AM, Michael Haggerty  wrote:
>> In set notation,
>>
>> "non-NULL" =
>> "non-NULL and not NULL_SHA1" ∪
>> "non-NULL and equal to NULL_SHA1"
>>
>> The latter two are *not* treated the same, so I don't see how we can
>> claim that "non-NULL" and "not NULL_SHA1" are treated the same. I must
>> be misunderstanding you.
>>
>> Would it help if I changed the comment to
>>
>> Delete the specified reference. If old_sha1 is non-NULL and not
>> NULL_SHA1, then verify that the current value of the reference is
>> old_sha1 before deleting it. If old_sha1 is NULL or NULL_SHA1,
>> delete the reference it it exists, regardless of its old value.
>>
>> ?
> 
> This is very clear to me.

OK, I will make the change in v2 (with s/it it/if it/).

Michael

-- 
Michael Haggerty
mhag...@alum.mit.edu

--
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 0/8] object_id part 2

2015-06-13 Thread Michael Haggerty
-BEGIN PGP SIGNED MESSAGE-
Hash: SHA1

On 06/13/2015 12:27 AM, brian m. carlson wrote:
> On Fri, Jun 12, 2015 at 03:14:25PM -0700, Junio C Hamano wrote:
>> "brian m. carlson"  writes:
>> 
>>> While I did run the tests between each commit, I hadn't noticed
>>> they were failing because I don't have Apache installed on my
>>> laptop, so they were silently skipped.  I'll resubmit with that
>>> fixed.
>> 
>> It is somewhat strange that _only_ http part had failures like
>> this, and is unnerving, too, given that a few people seem to have
>> given at least a cursory read over the patches and didn't spot
>> anything obviously wrong.
>> 
>> Was that because there was a single manual botch, or was that
>> merely that other parts of the system do not have sufficient test
>> coverage?
> 
> It appears that I broke the change in "parse_fetch: convert to use 
> struct object_id" which modifies remote-curl.c, so I think it's a
> single manual botch.  I'm going to rework that patch anyway since
> Michael said that he didn't like the idea of parse_oid_hex as it
> stands, so it will end up being mostly moot.

In the same email where I made those design suggestions, I also I
pointed out a bug in the implementation of parse_oid_hex(). Maybe that
is the reason for the test failures.

Michael

- -- 
Michael Haggerty
mhag...@alum.mit.edu


-BEGIN PGP SIGNATURE-
Version: GnuPG v2

iEYEARECAAYFAlV77aYACgkQwg9mrRwfmAnCyQCeIp9aSOTtQ1ABpiSybcFQFP87
fNwAoLNhQtyFQ2/fqQIvzl1gGEEOlWxa
=gI7/
-END PGP SIGNATURE-
--
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