[PATCH v2 Outreachy] mru: use double-linked list from list.h

2017-09-30 Thread Olga Telezhnaya
Simplify mru.[ch] and related code by reusing the double-linked list
implementation from list.h instead of a custom one.
This commit is an intermediate step. Our final goal is to get rid of
mru.[ch] at all and inline all logic.

Signed-off-by: Olga Telezhnaia 
Mentored-by: Christian Couder 
Mentored by: Jeff King 
---
 builtin/pack-objects.c |  5 +++--
 mru.c  | 49 +
 mru.h  | 31 +--
 packfile.c |  7 ---
 4 files changed, 33 insertions(+), 59 deletions(-)

diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c
index f721137eaf881..ba812349e0aab 100644
--- a/builtin/pack-objects.c
+++ b/builtin/pack-objects.c
@@ -995,8 +995,8 @@ static int want_object_in_pack(const unsigned char *sha1,
   struct packed_git **found_pack,
   off_t *found_offset)
 {
-   struct mru_entry *entry;
int want;
+   struct list_head *pos;
 
if (!exclude && local && has_loose_object_nonlocal(sha1))
return 0;
@@ -1012,7 +1012,8 @@ static int want_object_in_pack(const unsigned char *sha1,
return want;
}
 
-   for (entry = packed_git_mru.head; entry; entry = entry->next) {
+   list_for_each(pos, _git_mru.list) {
+   struct mru *entry = list_entry(pos, struct mru, list);
struct packed_git *p = entry->item;
off_t offset;
 
diff --git a/mru.c b/mru.c
index 9dedae0287ed2..8f3f34c5ba91d 100644
--- a/mru.c
+++ b/mru.c
@@ -1,50 +1,27 @@
 #include "cache.h"
 #include "mru.h"
 
-void mru_append(struct mru *mru, void *item)
+void mru_append(struct mru *head, void *item)
 {
-   struct mru_entry *cur = xmalloc(sizeof(*cur));
+   struct mru *cur = xmalloc(sizeof(*cur));
cur->item = item;
-   cur->prev = mru->tail;
-   cur->next = NULL;
-
-   if (mru->tail)
-   mru->tail->next = cur;
-   else
-   mru->head = cur;
-   mru->tail = cur;
+   list_add_tail(>list, >list);
 }
 
-void mru_mark(struct mru *mru, struct mru_entry *entry)
+void mru_mark(struct mru *head, struct mru *entry)
 {
-   /* If we're already at the front of the list, nothing to do */
-   if (mru->head == entry)
-   return;
-
-   /* Otherwise, remove us from our current slot... */
-   if (entry->prev)
-   entry->prev->next = entry->next;
-   if (entry->next)
-   entry->next->prev = entry->prev;
-   else
-   mru->tail = entry->prev;
-
-   /* And insert us at the beginning. */
-   entry->prev = NULL;
-   entry->next = mru->head;
-   if (mru->head)
-   mru->head->prev = entry;
-   mru->head = entry;
+   /* To mark means to put at the front of the list. */
+   list_del(>list);
+   list_add(>list, >list);
 }
 
-void mru_clear(struct mru *mru)
+void mru_clear(struct mru *head)
 {
-   struct mru_entry *p = mru->head;
+   struct list_head *pos;
+   struct list_head *tmp;
 
-   while (p) {
-   struct mru_entry *to_free = p;
-   p = p->next;
-   free(to_free);
+   list_for_each_safe(pos, tmp, >list) {
+   free(list_entry(pos, struct mru, list));
}
-   mru->head = mru->tail = NULL;
+   INIT_LIST_HEAD(>list);
 }
diff --git a/mru.h b/mru.h
index 42e4aeaa1098a..80a589eb4c0eb 100644
--- a/mru.h
+++ b/mru.h
@@ -1,6 +1,8 @@
 #ifndef MRU_H
 #define MRU_H
 
+#include "list.h"
+
 /**
  * A simple most-recently-used cache, backed by a doubly-linked list.
  *
@@ -8,18 +10,15 @@
  *
  *   // Create a list.  Zero-initialization is required.
  *   static struct mru cache;
- *   mru_append(, item);
- *   ...
+ *   INIT_LIST_HEAD();
  *
- *   // Iterate in MRU order.
- *   struct mru_entry *p;
- *   for (p = cache.head; p; p = p->next) {
- * if (matches(p->item))
- * break;
- *   }
+ *   // Add new item to the end of the list.
+ *   void *item;
+ *   ...
+ *   mru_append(, item);
  *
  *   // Mark an item as used, moving it to the front of the list.
- *   mru_mark(, p);
+ *   mru_mark(, item);
  *
  *   // Reset the list to empty, cleaning up all resources.
  *   mru_clear();
@@ -29,17 +28,13 @@
  * you will begin traversing the whole list again.
  */
 
-struct mru_entry {
-   void *item;
-   struct mru_entry *prev, *next;
-};
-
 struct mru {
-   struct mru_entry *head, *tail;
+   struct list_head list;
+   void *item;
 };
 
-void mru_append(struct mru *mru, void *item);
-void mru_mark(struct mru *mru, struct mru_entry *entry);
-void mru_clear(struct mru *mru);
+void mru_append(struct mru *head, void *item);
+void mru_mark(struct mru *head, struct mru *entry);
+void mru_clear(struct mru *head);
 
 #endif /* MRU_H */
diff --git a/packfile.c 

[PATCH Outreachy] mru: use double-linked list from list.h

2017-09-28 Thread Olga Telezhnaya
Simplify mru.c, mru.h and related code by reusing the double-linked list 
implementation from list.h instead of a custom one.

Signed-off-by: Olga Telezhnaia 
Mentored-by: Christian Couder 
Mentored by: Jeff King 
---
 builtin/pack-objects.c |  5 +++--
 mru.c  | 51 +++---
 mru.h  | 31 +-
 packfile.c |  6 --
 4 files changed, 35 insertions(+), 58 deletions(-)

diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c
index f721137eaf881..ba812349e0aab 100644
--- a/builtin/pack-objects.c
+++ b/builtin/pack-objects.c
@@ -995,8 +995,8 @@ static int want_object_in_pack(const unsigned char *sha1,
   struct packed_git **found_pack,
   off_t *found_offset)
 {
-   struct mru_entry *entry;
int want;
+   struct list_head *pos;
 
if (!exclude && local && has_loose_object_nonlocal(sha1))
return 0;
@@ -1012,7 +1012,8 @@ static int want_object_in_pack(const unsigned char *sha1,
return want;
}
 
-   for (entry = packed_git_mru.head; entry; entry = entry->next) {
+   list_for_each(pos, _git_mru.list) {
+   struct mru *entry = list_entry(pos, struct mru, list);
struct packed_git *p = entry->item;
off_t offset;
 
diff --git a/mru.c b/mru.c
index 9dedae0287ed2..8b6ba3d9b7fad 100644
--- a/mru.c
+++ b/mru.c
@@ -1,50 +1,29 @@
 #include "cache.h"
 #include "mru.h"
 
-void mru_append(struct mru *mru, void *item)
+void mru_append(struct mru *head, void *item)
 {
-   struct mru_entry *cur = xmalloc(sizeof(*cur));
+   struct mru *cur = xmalloc(sizeof(*cur));
cur->item = item;
-   cur->prev = mru->tail;
-   cur->next = NULL;
-
-   if (mru->tail)
-   mru->tail->next = cur;
-   else
-   mru->head = cur;
-   mru->tail = cur;
+   list_add_tail(>list, >list);
 }
 
-void mru_mark(struct mru *mru, struct mru_entry *entry)
+void mru_mark(struct mru *head, struct mru *entry)
 {
-   /* If we're already at the front of the list, nothing to do */
-   if (mru->head == entry)
-   return;
-
-   /* Otherwise, remove us from our current slot... */
-   if (entry->prev)
-   entry->prev->next = entry->next;
-   if (entry->next)
-   entry->next->prev = entry->prev;
-   else
-   mru->tail = entry->prev;
-
-   /* And insert us at the beginning. */
-   entry->prev = NULL;
-   entry->next = mru->head;
-   if (mru->head)
-   mru->head->prev = entry;
-   mru->head = entry;
+   /* To mark means to put at the front of the list. */
+   list_del(>list);
+   list_add(>list, >list);
 }
 
-void mru_clear(struct mru *mru)
+void mru_clear(struct mru *head)
 {
-   struct mru_entry *p = mru->head;
-
-   while (p) {
-   struct mru_entry *to_free = p;
-   p = p->next;
+   struct list_head *p1;
+   struct list_head *p2;
+   struct mru *to_free;
+   
+   list_for_each_safe(p1, p2, >list) {
+   to_free = list_entry(p1, struct mru, list);
free(to_free);
}
-   mru->head = mru->tail = NULL;
+   INIT_LIST_HEAD(>list);
 }
diff --git a/mru.h b/mru.h
index 42e4aeaa1098a..36a332af0bf88 100644
--- a/mru.h
+++ b/mru.h
@@ -1,6 +1,8 @@
 #ifndef MRU_H
 #define MRU_H
 
+#include "list.h"
+
 /**
  * A simple most-recently-used cache, backed by a doubly-linked list.
  *
@@ -8,18 +10,15 @@
  *
  *   // Create a list.  Zero-initialization is required.
  *   static struct mru cache;
- *   mru_append(, item);
- *   ...
+ *   INIT_LIST_HEAD();
  *
- *   // Iterate in MRU order.
- *   struct mru_entry *p;
- *   for (p = cache.head; p; p = p->next) {
- * if (matches(p->item))
- * break;
- *   }
+ *   // Add new item to the end of the list.
+ *   void *item;
+ *   ...
+ *   mru_append(, item);
  *
  *   // Mark an item as used, moving it to the front of the list.
- *   mru_mark(, p);
+ *   mru_mark(, item);
  *
  *   // Reset the list to empty, cleaning up all resources.
  *   mru_clear();
@@ -29,17 +28,13 @@
  * you will begin traversing the whole list again.
  */
 
-struct mru_entry {
-   void *item;
-   struct mru_entry *prev, *next;
-};
-
 struct mru {
-   struct mru_entry *head, *tail;
+   struct list_head list;
+void *item;
 };
 
-void mru_append(struct mru *mru, void *item);
-void mru_mark(struct mru *mru, struct mru_entry *entry);
-void mru_clear(struct mru *mru);
+void mru_append(struct mru *head, void *item);
+void mru_mark(struct mru *head, struct mru *entry);
+void mru_clear(struct mru *head);
 
 #endif /* MRU_H */
diff --git a/packfile.c b/packfile.c
index f69a5c8d607af..ae3b0b2e9c09a 100644
--- a/packfile.c
+++ 

[PATCH Outreachy 1/2] format: create pretty.h file

2017-12-08 Thread Olga Telezhnaya
Create header for pretty.c to make formatting interface more structured.
This is a middle point, this file would be merged futher with other
files which contain formatting stuff.

Signed-off-by: Olga Telezhnaia 
Mentored-by: Christian Couder 
Mentored by: Jeff King 
---
 archive.c |  1 +
 builtin/notes.c   |  2 +-
 builtin/reset.c   |  2 +-
 builtin/show-branch.c |  2 +-
 combine-diff.c|  1 +
 commit.c  |  1 +
 commit.h  | 80 --
 diffcore-pickaxe.c|  1 +
 grep.c|  1 +
 log-tree.c|  1 +
 notes-cache.c |  1 +
 pretty.h  | 87 +++
 revision.h|  2 +-
 sequencer.c   |  1 +
 sha1_name.c   |  1 +
 submodule.c   |  1 +
 16 files changed, 101 insertions(+), 84 deletions(-)
 create mode 100644 pretty.h

diff --git a/archive.c b/archive.c
index 0b7b62af0c3ec..60607e8c00857 100644
--- a/archive.c
+++ b/archive.c
@@ -2,6 +2,7 @@
 #include "config.h"
 #include "refs.h"
 #include "commit.h"
+#include "pretty.h"
 #include "tree-walk.h"
 #include "attr.h"
 #include "archive.h"
diff --git a/builtin/notes.c b/builtin/notes.c
index 1a2c7d92ad7e7..7c8176164561b 100644
--- a/builtin/notes.c
+++ b/builtin/notes.c
@@ -12,7 +12,7 @@
 #include "builtin.h"
 #include "notes.h"
 #include "blob.h"
-#include "commit.h"
+#include "pretty.h"
 #include "refs.h"
 #include "exec_cmd.h"
 #include "run-command.h"
diff --git a/builtin/reset.c b/builtin/reset.c
index 906e541658230..e15f595799c40 100644
--- a/builtin/reset.c
+++ b/builtin/reset.c
@@ -12,7 +12,7 @@
 #include "lockfile.h"
 #include "tag.h"
 #include "object.h"
-#include "commit.h"
+#include "pretty.h"
 #include "run-command.h"
 #include "refs.h"
 #include "diff.h"
diff --git a/builtin/show-branch.c b/builtin/show-branch.c
index 2e24b5c330e8e..e8a4aa40cb4b6 100644
--- a/builtin/show-branch.c
+++ b/builtin/show-branch.c
@@ -1,6 +1,6 @@
 #include "cache.h"
 #include "config.h"
-#include "commit.h"
+#include "pretty.h"
 #include "refs.h"
 #include "builtin.h"
 #include "color.h"
diff --git a/combine-diff.c b/combine-diff.c
index 2505de119a2be..01ba1b03a06d2 100644
--- a/combine-diff.c
+++ b/combine-diff.c
@@ -1,5 +1,6 @@
 #include "cache.h"
 #include "commit.h"
+#include "pretty.h"
 #include "blob.h"
 #include "diff.h"
 #include "diffcore.h"
diff --git a/commit.c b/commit.c
index cab8d4455bdbd..ac17a27a4ab0a 100644
--- a/commit.c
+++ b/commit.c
@@ -1,6 +1,7 @@
 #include "cache.h"
 #include "tag.h"
 #include "commit.h"
+#include "pretty.h"
 #include "pkt-line.h"
 #include "utf8.h"
 #include "diff.h"
diff --git a/commit.h b/commit.h
index 99a3fea68d3f6..41a2067809444 100644
--- a/commit.h
+++ b/commit.h
@@ -121,93 +121,13 @@ struct commit_list *copy_commit_list(struct commit_list 
*list);
 
 void free_commit_list(struct commit_list *list);
 
-/* Commit formats */
-enum cmit_fmt {
-   CMIT_FMT_RAW,
-   CMIT_FMT_MEDIUM,
-   CMIT_FMT_DEFAULT = CMIT_FMT_MEDIUM,
-   CMIT_FMT_SHORT,
-   CMIT_FMT_FULL,
-   CMIT_FMT_FULLER,
-   CMIT_FMT_ONELINE,
-   CMIT_FMT_EMAIL,
-   CMIT_FMT_MBOXRD,
-   CMIT_FMT_USERFORMAT,
-
-   CMIT_FMT_UNSPECIFIED
-};
-
-static inline int cmit_fmt_is_mail(enum cmit_fmt fmt)
-{
-   return (fmt == CMIT_FMT_EMAIL || fmt == CMIT_FMT_MBOXRD);
-}
-
 struct rev_info; /* in revision.h, it circularly uses enum cmit_fmt */
 
-struct pretty_print_context {
-   /*
-* Callers should tweak these to change the behavior of pp_* functions.
-*/
-   enum cmit_fmt fmt;
-   int abbrev;
-   const char *after_subject;
-   int preserve_subject;
-   struct date_mode date_mode;
-   unsigned date_mode_explicit:1;
-   int print_email_subject;
-   int expand_tabs_in_log;
-   int need_8bit_cte;
-   char *notes_message;
-   struct reflog_walk_info *reflog_info;
-   struct rev_info *rev;
-   const char *output_encoding;
-   struct string_list *mailmap;
-   int color;
-   struct ident_split *from_ident;
-
-   /*
-* Fields below here are manipulated internally by pp_* functions and
-* should not be counted on by callers.
-*/
-   struct string_list in_body_headers;
-   int graph_width;
-};
-
-struct userformat_want {
-   unsigned notes:1;
-};
-
 extern int has_non_ascii(const char *text);
 extern const char *logmsg_reencode(const struct commit *commit,
   char **commit_encoding,
   const char *output_encoding);
-extern void get_commit_format(const char *arg, struct rev_info *);
-extern const char *format_subject(struct strbuf *sb, const char *msg,
- const char *line_separator);
-extern void userformat_find_requirements(const char *fmt, struct 

[PATCH Outreachy 2/2] format: create docs for pretty.h

2017-12-08 Thread Olga Telezhnaya
Write some docs for functions in pretty.h.
Take it as a first draft, they would be changed later.

Signed-off-by: Olga Telezhnaia 
Mentored-by: Christian Couder 
Mentored by: Jeff King 
---
 pretty.h | 44 
 1 file changed, 44 insertions(+)

diff --git a/pretty.h b/pretty.h
index ef5167484fb64..5c85d94e332d7 100644
--- a/pretty.h
+++ b/pretty.h
@@ -48,6 +48,7 @@ struct pretty_print_context {
int graph_width;
 };
 
+/* Check whether commit format is mail. */
 static inline int cmit_fmt_is_mail(enum cmit_fmt fmt)
 {
return (fmt == CMIT_FMT_EMAIL || fmt == CMIT_FMT_MBOXRD);
@@ -57,31 +58,74 @@ struct userformat_want {
unsigned notes:1;
 };
 
+/* Set the flag "w->notes" if there is placeholder %N in "fmt". */
 void userformat_find_requirements(const char *fmt, struct userformat_want *w);
+
+/*
+ * Shortcut for invoking pretty_print_commit if we do not have any context.
+ * Context would be set empty except "fmt".
+ */
 void pp_commit_easy(enum cmit_fmt fmt, const struct commit *commit,
struct strbuf *sb);
+
+/*
+ * Get information about user and date from "line", format it and
+ * put it into "sb".
+ * Format of "line" must be readable for split_ident_line function.
+ * The resulting format is "what: name  date".
+ */
 void pp_user_info(struct pretty_print_context *pp, const char *what,
struct strbuf *sb, const char *line,
const char *encoding);
+
+/*
+ * Format title line of commit message taken from "msg_p" and
+ * put it into "sb".
+ * First line of "msg_p" is also affected.
+ */
 void pp_title_line(struct pretty_print_context *pp, const char **msg_p,
struct strbuf *sb, const char *encoding,
int need_8bit_cte);
+
+/*
+ * Get current state of commit message from "msg_p" and continue formatting
+ * by adding indentation and '>' signs. Put result into "sb".
+ */
 void pp_remainder(struct pretty_print_context *pp, const char **msg_p,
struct strbuf *sb, int indent);
 
+/*
+ * Create a text message about commit using given "format" and "context".
+ * Put the result to "sb".
+ * Please use this function for custom formats.
+ */
 void format_commit_message(const struct commit *commit,
const char *format, struct strbuf *sb,
const struct pretty_print_context *context);
 
+/*
+ * Parse given arguments from "arg", check it for correctness and
+ * fill struct rev_info.
+ */
 void get_commit_format(const char *arg, struct rev_info *);
 
+/*
+ * Make a commit message with all rules from given "pp"
+ * and put it into "sb".
+ * Please use this function if you have a context (candidate for "pp").
+ */
 void pretty_print_commit(struct pretty_print_context *pp,
const struct commit *commit,
struct strbuf *sb);
 
+/*
+ * Change line breaks in "msg" to "line_separator" and put it into "sb".
+ * Return "msg" itself.
+ */
 const char *format_subject(struct strbuf *sb, const char *msg,
const char *line_separator);
 
+/* Check if "cmit_fmt" will produce an empty output. */
 int commit_format_is_empty(enum cmit_fmt);
 
 #endif /* PRETTY_H */

--
https://github.com/git/git/pull/439


[PATCH Outreachy v2 1/2] format: create pretty.h file

2017-12-12 Thread Olga Telezhnaya
Create header for pretty.c to make formatting interface more structured.
This is a middle point, this file would be merged further with other
files which contain formatting stuff.

Signed-off-by: Olga Telezhnaia 
Mentored-by: Christian Couder 
Mentored by: Jeff King 
---
 builtin/notes.c   |  2 +-
 builtin/reset.c   |  2 +-
 builtin/show-branch.c |  2 +-
 commit.h  | 81 +--
 pretty.h  | 87 +++
 revision.h|  2 +-
 6 files changed, 92 insertions(+), 84 deletions(-)
 create mode 100644 pretty.h

diff --git a/builtin/notes.c b/builtin/notes.c
index 1a2c7d92ad7e7..7c8176164561b 100644
--- a/builtin/notes.c
+++ b/builtin/notes.c
@@ -12,7 +12,7 @@
 #include "builtin.h"
 #include "notes.h"
 #include "blob.h"
-#include "commit.h"
+#include "pretty.h"
 #include "refs.h"
 #include "exec_cmd.h"
 #include "run-command.h"
diff --git a/builtin/reset.c b/builtin/reset.c
index 906e541658230..e15f595799c40 100644
--- a/builtin/reset.c
+++ b/builtin/reset.c
@@ -12,7 +12,7 @@
 #include "lockfile.h"
 #include "tag.h"
 #include "object.h"
-#include "commit.h"
+#include "pretty.h"
 #include "run-command.h"
 #include "refs.h"
 #include "diff.h"
diff --git a/builtin/show-branch.c b/builtin/show-branch.c
index 2e24b5c330e8e..e8a4aa40cb4b6 100644
--- a/builtin/show-branch.c
+++ b/builtin/show-branch.c
@@ -1,6 +1,6 @@
 #include "cache.h"
 #include "config.h"
-#include "commit.h"
+#include "pretty.h"
 #include "refs.h"
 #include "builtin.h"
 #include "color.h"
diff --git a/commit.h b/commit.h
index 99a3fea68d3f6..8c68ca1a5a187 100644
--- a/commit.h
+++ b/commit.h
@@ -7,6 +7,7 @@
 #include "decorate.h"
 #include "gpg-interface.h"
 #include "string-list.h"
+#include "pretty.h"
 
 struct commit_list {
struct commit *item;
@@ -121,93 +122,13 @@ struct commit_list *copy_commit_list(struct commit_list 
*list);
 
 void free_commit_list(struct commit_list *list);
 
-/* Commit formats */
-enum cmit_fmt {
-   CMIT_FMT_RAW,
-   CMIT_FMT_MEDIUM,
-   CMIT_FMT_DEFAULT = CMIT_FMT_MEDIUM,
-   CMIT_FMT_SHORT,
-   CMIT_FMT_FULL,
-   CMIT_FMT_FULLER,
-   CMIT_FMT_ONELINE,
-   CMIT_FMT_EMAIL,
-   CMIT_FMT_MBOXRD,
-   CMIT_FMT_USERFORMAT,
-
-   CMIT_FMT_UNSPECIFIED
-};
-
-static inline int cmit_fmt_is_mail(enum cmit_fmt fmt)
-{
-   return (fmt == CMIT_FMT_EMAIL || fmt == CMIT_FMT_MBOXRD);
-}
-
 struct rev_info; /* in revision.h, it circularly uses enum cmit_fmt */
 
-struct pretty_print_context {
-   /*
-* Callers should tweak these to change the behavior of pp_* functions.
-*/
-   enum cmit_fmt fmt;
-   int abbrev;
-   const char *after_subject;
-   int preserve_subject;
-   struct date_mode date_mode;
-   unsigned date_mode_explicit:1;
-   int print_email_subject;
-   int expand_tabs_in_log;
-   int need_8bit_cte;
-   char *notes_message;
-   struct reflog_walk_info *reflog_info;
-   struct rev_info *rev;
-   const char *output_encoding;
-   struct string_list *mailmap;
-   int color;
-   struct ident_split *from_ident;
-
-   /*
-* Fields below here are manipulated internally by pp_* functions and
-* should not be counted on by callers.
-*/
-   struct string_list in_body_headers;
-   int graph_width;
-};
-
-struct userformat_want {
-   unsigned notes:1;
-};
-
 extern int has_non_ascii(const char *text);
 extern const char *logmsg_reencode(const struct commit *commit,
   char **commit_encoding,
   const char *output_encoding);
-extern void get_commit_format(const char *arg, struct rev_info *);
-extern const char *format_subject(struct strbuf *sb, const char *msg,
- const char *line_separator);
-extern void userformat_find_requirements(const char *fmt, struct 
userformat_want *w);
-extern int commit_format_is_empty(enum cmit_fmt);
 extern const char *skip_blank_lines(const char *msg);
-extern void format_commit_message(const struct commit *commit,
- const char *format, struct strbuf *sb,
- const struct pretty_print_context *context);
-extern void pretty_print_commit(struct pretty_print_context *pp,
-   const struct commit *commit,
-   struct strbuf *sb);
-extern void pp_commit_easy(enum cmit_fmt fmt, const struct commit *commit,
-  struct strbuf *sb);
-void pp_user_info(struct pretty_print_context *pp,
- const char *what, struct strbuf *sb,
- const char *line, const char *encoding);
-void pp_title_line(struct pretty_print_context *pp,
-  const char **msg_p,
-  struct strbuf *sb,

[PATCH Outreachy v2 2/2] format: create docs for pretty.h

2017-12-12 Thread Olga Telezhnaya
Write some docs for functions in pretty.h.
Take it as a first draft, they would be changed later.

Signed-off-by: Olga Telezhnaia 
Mentored-by: Christian Couder 
Mentored by: Jeff King 
---
 pretty.h | 44 
 1 file changed, 44 insertions(+)

diff --git a/pretty.h b/pretty.h
index ef5167484fb64..5c85d94e332d7 100644
--- a/pretty.h
+++ b/pretty.h
@@ -48,6 +48,7 @@ struct pretty_print_context {
int graph_width;
 };
 
+/* Check whether commit format is mail. */
 static inline int cmit_fmt_is_mail(enum cmit_fmt fmt)
 {
return (fmt == CMIT_FMT_EMAIL || fmt == CMIT_FMT_MBOXRD);
@@ -57,31 +58,74 @@ struct userformat_want {
unsigned notes:1;
 };
 
+/* Set the flag "w->notes" if there is placeholder %N in "fmt". */
 void userformat_find_requirements(const char *fmt, struct userformat_want *w);
+
+/*
+ * Shortcut for invoking pretty_print_commit if we do not have any context.
+ * Context would be set empty except "fmt".
+ */
 void pp_commit_easy(enum cmit_fmt fmt, const struct commit *commit,
struct strbuf *sb);
+
+/*
+ * Get information about user and date from "line", format it and
+ * put it into "sb".
+ * Format of "line" must be readable for split_ident_line function.
+ * The resulting format is "what: name  date".
+ */
 void pp_user_info(struct pretty_print_context *pp, const char *what,
struct strbuf *sb, const char *line,
const char *encoding);
+
+/*
+ * Format title line of commit message taken from "msg_p" and
+ * put it into "sb".
+ * First line of "msg_p" is also affected.
+ */
 void pp_title_line(struct pretty_print_context *pp, const char **msg_p,
struct strbuf *sb, const char *encoding,
int need_8bit_cte);
+
+/*
+ * Get current state of commit message from "msg_p" and continue formatting
+ * by adding indentation and '>' signs. Put result into "sb".
+ */
 void pp_remainder(struct pretty_print_context *pp, const char **msg_p,
struct strbuf *sb, int indent);
 
+/*
+ * Create a text message about commit using given "format" and "context".
+ * Put the result to "sb".
+ * Please use this function for custom formats.
+ */
 void format_commit_message(const struct commit *commit,
const char *format, struct strbuf *sb,
const struct pretty_print_context *context);
 
+/*
+ * Parse given arguments from "arg", check it for correctness and
+ * fill struct rev_info.
+ */
 void get_commit_format(const char *arg, struct rev_info *);
 
+/*
+ * Make a commit message with all rules from given "pp"
+ * and put it into "sb".
+ * Please use this function if you have a context (candidate for "pp").
+ */
 void pretty_print_commit(struct pretty_print_context *pp,
const struct commit *commit,
struct strbuf *sb);
 
+/*
+ * Change line breaks in "msg" to "line_separator" and put it into "sb".
+ * Return "msg" itself.
+ */
 const char *format_subject(struct strbuf *sb, const char *msg,
const char *line_separator);
 
+/* Check if "cmit_fmt" will produce an empty output. */
 int commit_format_is_empty(enum cmit_fmt);
 
 #endif /* PRETTY_H */

--
https://github.com/git/git/pull/439


[PATCH RFC] ref-filter: start using oid_object_info

2018-05-14 Thread Olga Telezhnaya
Start using oid_object_info_extended(). So, if info from this function
is enough, we do not need to get and parse whole object (as it was before).
It's good for 3 reasons:
1. Some Git commands potentially will work faster.
2. It's much easier to add support for objectsize:disk and deltabase.
   (I have plans to add this support further)
3. It's easier to move formatting from cat-file command to this logic
   (It pretends to be unified formatting logic in the end)

Signed-off-by: Olga Telezhnaia 
---
 ref-filter.c | 34 +++---
 ref-filter.h | 21 +
 2 files changed, 52 insertions(+), 3 deletions(-)

diff --git a/ref-filter.c b/ref-filter.c
index 39e2744c949bb..7c4693ed084bb 100644
--- a/ref-filter.c
+++ b/ref-filter.c
@@ -100,6 +100,7 @@ static struct used_atom {
} u;
 } *used_atom;
 static int used_atom_cnt, need_tagged, need_symref;
+static struct expand_data format_data;
 
 /*
  * Expand string, append it to strbuf *sb, then return error code ret.
@@ -267,6 +268,22 @@ static int contents_atom_parser(const struct ref_format 
*format, struct used_ato
return 0;
 }
 
+static int objecttype_atom_parser(const struct ref_format *format, struct 
used_atom *atom,
+ const char *arg, struct strbuf *unused_err)
+{
+   format_data.use_data = 1;
+   format_data.info.typep = _data.type;
+   return 0;
+}
+
+static int objectsize_atom_parser(const struct ref_format *format, struct 
used_atom *atom,
+ const char *arg, struct strbuf *unused_err)
+{
+   format_data.use_data = 1;
+   format_data.info.sizep = _data.size;
+   return 0;
+}
+
 static int objectname_atom_parser(const struct ref_format *format, struct 
used_atom *atom,
  const char *arg, struct strbuf *err)
 {
@@ -383,9 +400,9 @@ static struct {
int (*parser)(const struct ref_format *format, struct used_atom *atom,
  const char *arg, struct strbuf *err);
 } valid_atom[] = {
-   { "refname" , FIELD_STR, refname_atom_parser },
-   { "objecttype" },
-   { "objectsize", FIELD_ULONG },
+   { "refname", FIELD_STR, refname_atom_parser },
+   { "objecttype", FIELD_STR, objecttype_atom_parser },
+   { "objectsize", FIELD_ULONG, objectsize_atom_parser },
{ "objectname", FIELD_STR, objectname_atom_parser },
{ "tree" },
{ "parent" },
@@ -1536,6 +1553,13 @@ static int populate_value(struct ref_array_item *ref, 
struct strbuf *err)
continue;
} else if (!deref && grab_objectname(name, >objectname, v, 
atom)) {
continue;
+   } else if (!deref && !strcmp(name, "objecttype")) {
+   v->s = type_name(format_data.type);
+   continue;
+   } else if (!deref && !strcmp(name, "objectsize")) {
+   v->value = format_data.size;
+   v->s = xstrfmt("%lu", format_data.size);
+   continue;
} else if (!strcmp(name, "HEAD")) {
if (atom->u.head && !strcmp(ref->refname, atom->u.head))
v->s = "*";
@@ -2226,6 +2250,10 @@ int format_ref_array_item(struct ref_array_item *info,
 {
const char *cp, *sp, *ep;
struct ref_formatting_state state = REF_FORMATTING_STATE_INIT;
+   format_data.oid = info->objectname;
+   if (format_data.use_data && oid_object_info_extended(_data.oid, 
_data.info,
+
OBJECT_INFO_LOOKUP_REPLACE) < 0)
+   return strbuf_addf_ret(error_buf, -1, "format: could not get 
object info");
 
state.quote_style = format->quote_style;
push_stack_element();
diff --git a/ref-filter.h b/ref-filter.h
index 85c8ebc3b904e..857e8c5318a8f 100644
--- a/ref-filter.h
+++ b/ref-filter.h
@@ -85,6 +85,27 @@ struct ref_format {
int need_color_reset_at_eol;
 };
 
+struct expand_data {
+   struct object_id oid;
+   enum object_type type;
+   unsigned long size;
+   off_t disk_size;
+   struct object_id delta_base_oid;
+
+   /*
+* This object_info is set up to be passed to oid_object_info_extended.
+* It will point to the data elements above, so you can retrieve
+* the response from there.
+*/
+   struct object_info info;
+
+   /*
+* This flag will be true if the requested format and options
+* require us to call oid_object_info_extended.
+*/
+   unsigned use_data : 1;
+};
+
 #define REF_FORMAT_INIT { NULL, 0, -1 }
 
 /*  Macros for checking --merged and --no-merged options */

--
https://github.com/git/git/pull/493


[PATCH RFC v2 1/4] ref-filter: start using oid_object_info

2018-05-18 Thread Olga Telezhnaya
Start using oid_object_info_extended(). So, if info from this function
is enough, we do not need to get and parse whole object (as it was before).
It's good for 3 reasons:
1. Some Git commands potentially will work faster.
2. It's much easier to add support for objectsize:disk and deltabase.
   (I have plans to add this support further)
3. It's easier to move formatting from cat-file command to this logic
   (It pretends to be unified formatting logic in the end)

Signed-off-by: Olga Telezhnaia 
---
 ref-filter.c | 47 +++
 ref-filter.h | 21 +
 2 files changed, 64 insertions(+), 4 deletions(-)

diff --git a/ref-filter.c b/ref-filter.c
index 39e2744c949bb..4008351553391 100644
--- a/ref-filter.c
+++ b/ref-filter.c
@@ -100,6 +100,7 @@ static struct used_atom {
} u;
 } *used_atom;
 static int used_atom_cnt, need_tagged, need_symref;
+static struct expand_data oi_data;
 
 /*
  * Expand string, append it to strbuf *sb, then return error code ret.
@@ -267,6 +268,22 @@ static int contents_atom_parser(const struct ref_format 
*format, struct used_ato
return 0;
 }
 
+static int objecttype_atom_parser(const struct ref_format *format, struct 
used_atom *atom,
+ const char *arg, struct strbuf *unused_err)
+{
+   oi_data.use_data = 1;
+   oi_data.info.typep = _data.type;
+   return 0;
+}
+
+static int objectsize_atom_parser(const struct ref_format *format, struct 
used_atom *atom,
+ const char *arg, struct strbuf *unused_err)
+{
+   oi_data.use_data = 1;
+   oi_data.info.sizep = _data.size;
+   return 0;
+}
+
 static int objectname_atom_parser(const struct ref_format *format, struct 
used_atom *atom,
  const char *arg, struct strbuf *err)
 {
@@ -383,9 +400,9 @@ static struct {
int (*parser)(const struct ref_format *format, struct used_atom *atom,
  const char *arg, struct strbuf *err);
 } valid_atom[] = {
-   { "refname" , FIELD_STR, refname_atom_parser },
-   { "objecttype" },
-   { "objectsize", FIELD_ULONG },
+   { "refname", FIELD_STR, refname_atom_parser },
+   { "objecttype", FIELD_STR, objecttype_atom_parser },
+   { "objectsize", FIELD_ULONG, objectsize_atom_parser },
{ "objectname", FIELD_STR, objectname_atom_parser },
{ "tree" },
{ "parent" },
@@ -1207,7 +1224,8 @@ static void fill_missing_values(struct atom_value *val)
  */
 static void grab_values(struct atom_value *val, int deref, struct object *obj, 
void *buf, unsigned long sz)
 {
-   grab_common_values(val, deref, obj, buf, sz);
+   if (deref || !oi_data.use_data)
+   grab_common_values(val, deref, obj, buf, sz);
switch (obj->type) {
case OBJ_TAG:
grab_tag_values(val, deref, obj, buf, sz);
@@ -1536,6 +1554,13 @@ static int populate_value(struct ref_array_item *ref, 
struct strbuf *err)
continue;
} else if (!deref && grab_objectname(name, >objectname, v, 
atom)) {
continue;
+   } else if (!deref && !strcmp(name, "objecttype") && 
oi_data.use_data) {
+   v->s = type_name(oi_data.type);
+   continue;
+   } else if (!deref && !strcmp(name, "objectsize") && 
oi_data.use_data) {
+   v->value = oi_data.size;
+   v->s = xstrfmt("%lu", oi_data.size);
+   continue;
} else if (!strcmp(name, "HEAD")) {
if (atom->u.head && !strcmp(ref->refname, atom->u.head))
v->s = "*";
@@ -2156,8 +2181,17 @@ static int cmp_ref_sorting(struct ref_sorting *s, struct 
ref_array_item *a, stru
int (*cmp_fn)(const char *, const char *);
struct strbuf err = STRBUF_INIT;
 
+   oi_data.oid = a->objectname;
+   if (oi_data.use_data &&
+   oid_object_info_extended(_data.oid, _data.info, 
OBJECT_INFO_LOOKUP_REPLACE) < 0)
+   die(_("missing object %s for %s"), oid_to_hex(>objectname), 
a->refname);
if (get_ref_atom_value(a, s->atom, , ))
die("%s", err.buf);
+
+   oi_data.oid = b->objectname;
+   if (oi_data.use_data &&
+   oid_object_info_extended(_data.oid, _data.info, 
OBJECT_INFO_LOOKUP_REPLACE) < 0)
+   die(_("missing object %s for %s"), oid_to_hex(>objectname), 
b->refname);
if (get_ref_atom_value(b, s->atom, , ))
die("%s", err.buf);
strbuf_release();
@@ -2226,6 +2260,11 @@ int format_ref_array_item(struct ref_array_item *info,
 {
const char *cp, *sp, *ep;
struct ref_formatting_state state = REF_FORMATTING_STATE_INIT;
+   oi_data.oid = info->objectname;
+   if (oi_data.use_data &&
+   oid_object_info_extended(_data.oid, 

[PATCH RFC v2 2/4] ref-filter: add objectsize:disk formatting option

2018-05-18 Thread Olga Telezhnaya
Add %(objectsize:disk) support. It is still not working for deref:
I am thinking how to support it in a more elegant way.

Signed-off-by: Olga Telezhnaia 
---
 ref-filter.c | 21 -
 1 file changed, 16 insertions(+), 5 deletions(-)

diff --git a/ref-filter.c b/ref-filter.c
index 4008351553391..c00de58455301 100644
--- a/ref-filter.c
+++ b/ref-filter.c
@@ -277,10 +277,15 @@ static int objecttype_atom_parser(const struct ref_format 
*format, struct used_a
 }
 
 static int objectsize_atom_parser(const struct ref_format *format, struct 
used_atom *atom,
- const char *arg, struct strbuf *unused_err)
+ const char *arg, struct strbuf *err)
 {
+   if (!arg)
+   oi_data.info.sizep = _data.size;
+   else if (!strcmp(arg, "disk"))
+   oi_data.info.disk_sizep = _data.disk_size;
+   else
+   return strbuf_addf_ret(err, -1, _("unrecognized %%(objectsize) 
argument: %s"), arg);
oi_data.use_data = 1;
-   oi_data.info.sizep = _data.size;
return 0;
 }
 
@@ -1557,9 +1562,15 @@ static int populate_value(struct ref_array_item *ref, 
struct strbuf *err)
} else if (!deref && !strcmp(name, "objecttype") && 
oi_data.use_data) {
v->s = type_name(oi_data.type);
continue;
-   } else if (!deref && !strcmp(name, "objectsize") && 
oi_data.use_data) {
-   v->value = oi_data.size;
-   v->s = xstrfmt("%lu", oi_data.size);
+   } else if (!deref && starts_with(name, "objectsize") && 
oi_data.use_data) {
+   if (!strcmp(name, "objectsize")) {
+   v->value = oi_data.size;
+   v->s = xstrfmt("%lu", oi_data.size);
+   } else {
+   /* It can be only objectsize:disk, we checked 
it in parser */
+   v->value = oi_data.disk_size;
+   v->s = xstrfmt("%lu", oi_data.disk_size);
+   }
continue;
} else if (!strcmp(name, "HEAD")) {
if (atom->u.head && !strcmp(ref->refname, atom->u.head))

--
https://github.com/git/git/pull/493


[PATCH RFC v2 4/4] ref-filter: add deltabase formatting option

2018-05-18 Thread Olga Telezhnaya
Add %(deltabase) support. It is still not working for deref:
I am thinking how to support it in a more elegant way.

Signed-off-by: Olga Telezhnaia 
---
 ref-filter.c | 12 
 1 file changed, 12 insertions(+)

diff --git a/ref-filter.c b/ref-filter.c
index c00de58455301..989ccdb356a32 100644
--- a/ref-filter.c
+++ b/ref-filter.c
@@ -276,6 +276,14 @@ static int objecttype_atom_parser(const struct ref_format 
*format, struct used_a
return 0;
 }
 
+static int deltabase_atom_parser(const struct ref_format *format, struct 
used_atom *atom,
+ const char *arg, struct strbuf *unused_err)
+{
+   oi_data.use_data = 1;
+   oi_data.info.delta_base_sha1 = oi_data.delta_base_oid.hash;
+   return 0;
+}
+
 static int objectsize_atom_parser(const struct ref_format *format, struct 
used_atom *atom,
  const char *arg, struct strbuf *err)
 {
@@ -409,6 +417,7 @@ static struct {
{ "objecttype", FIELD_STR, objecttype_atom_parser },
{ "objectsize", FIELD_ULONG, objectsize_atom_parser },
{ "objectname", FIELD_STR, objectname_atom_parser },
+   { "deltabase", FIELD_STR, deltabase_atom_parser },
{ "tree" },
{ "parent" },
{ "numparent", FIELD_ULONG },
@@ -1572,6 +1581,9 @@ static int populate_value(struct ref_array_item *ref, 
struct strbuf *err)
v->s = xstrfmt("%lu", oi_data.disk_size);
}
continue;
+   } else if (!deref && !strcmp(name, "deltabase") && 
oi_data.use_data) {
+   v->s = xstrdup(oid_to_hex(_data.delta_base_oid));
+   continue;
} else if (!strcmp(name, "HEAD")) {
if (atom->u.head && !strcmp(ref->refname, atom->u.head))
v->s = "*";

--
https://github.com/git/git/pull/493


[PATCH RFC v2 3/4] ref-filter: add tests for objectsize:disk

2018-05-18 Thread Olga Telezhnaya
Add tests for %(objectsize:disk) atom.

Signed-off-by: Olga Telezhnaia 
---
 t/t6300-for-each-ref.sh | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/t/t6300-for-each-ref.sh b/t/t6300-for-each-ref.sh
index 295d1475bde01..570bb606045d7 100755
--- a/t/t6300-for-each-ref.sh
+++ b/t/t6300-for-each-ref.sh
@@ -83,6 +83,7 @@ test_atom head push:strip=1 remotes/myfork/master
 test_atom head push:strip=-1 master
 test_atom head objecttype commit
 test_atom head objectsize 171
+test_atom head objectsize:disk 138
 test_atom head objectname $(git rev-parse refs/heads/master)
 test_atom head objectname:short $(git rev-parse --short refs/heads/master)
 test_atom head objectname:short=1 $(git rev-parse --short=1 refs/heads/master)
@@ -124,6 +125,7 @@ test_atom tag upstream ''
 test_atom tag push ''
 test_atom tag objecttype tag
 test_atom tag objectsize 154
+test_atom tag objectsize:disk 138
 test_atom tag objectname $(git rev-parse refs/tags/testtag)
 test_atom tag objectname:short $(git rev-parse --short refs/tags/testtag)
 test_atom head objectname:short=1 $(git rev-parse --short=1 refs/heads/master)

--
https://github.com/git/git/pull/493


[PATCH v2 10/18] cat-file: get rid of duplicate checking

2018-01-10 Thread Olga Telezhnaya
We could remove this because we have already checked that
at verify_ref_format function in ref-filter.

Signed-off-by: Olga Telezhnaia 
Mentored-by: Christian Couder 
Mentored by: Jeff King 
---
 builtin/cat-file.c | 2 --
 1 file changed, 2 deletions(-)

diff --git a/builtin/cat-file.c b/builtin/cat-file.c
index dd43457c0ad7e..1f331559e55c7 100644
--- a/builtin/cat-file.c
+++ b/builtin/cat-file.c
@@ -197,8 +197,6 @@ static void expand_atom(struct strbuf *sb, const char 
*atom, int len,
strbuf_addstr(sb, data->rest);
else if (is_atom("deltabase", atom, len))
strbuf_addstr(sb, oid_to_hex(>delta_base_oid));
-   else
-   die("unknown format element: %.*s", len, atom);
 }
 
 static size_t expand_format(struct strbuf *sb, const char *start, void *vdata)

--
https://github.com/git/git/pull/450


[PATCH v2 05/18] cat-file: start migrating to ref-filter

2018-01-10 Thread Olga Telezhnaya
Start moving all formatting stuff from cat-file to ref-filter.
Start from simple moving, it would be integrated into
all ref-filter processes further.

Signed-off-by: Olga Telezhnaia 
Mentored-by: Christian Couder 
Mentored by: Jeff King 
---
 builtin/cat-file.c |  5 ++---
 ref-filter.c   | 41 -
 ref-filter.h   |  6 ++
 3 files changed, 44 insertions(+), 8 deletions(-)

diff --git a/builtin/cat-file.c b/builtin/cat-file.c
index 7fd5b960ad698..0a3f4a47bf1ae 100644
--- a/builtin/cat-file.c
+++ b/builtin/cat-file.c
@@ -420,9 +420,8 @@ static int batch_objects(struct batch_options *opt)
 * object.
 */
memset(, 0, sizeof(data));
-   data.mark_query = 1;
-   strbuf_expand(, opt->format->format, expand_format, );
-   data.mark_query = 0;
+   opt->format->cat_file_data = 
+   verify_ref_format(opt->format);
if (opt->cmdmode)
data.split_on_whitespace = 1;
 
diff --git a/ref-filter.c b/ref-filter.c
index 32b7e918bca75..6ca4a671086ee 100644
--- a/ref-filter.c
+++ b/ref-filter.c
@@ -392,6 +392,31 @@ struct atom_value {
struct used_atom *atom;
 };
 
+static int is_atom(const char *atom, const char *s, int slen)
+{
+   int alen = strlen(atom);
+   return alen == slen && !memcmp(atom, s, alen);
+}
+
+static void expand_atom_into_fields(const char *atom, int len,
+   struct expand_data *data)
+{
+   if (is_atom("objectname", atom, len))
+   ; /* do nothing */
+   else if (is_atom("objecttype", atom, len))
+   data->info.typep = >type;
+   else if (is_atom("objectsize", atom, len))
+   data->info.sizep = >size;
+   else if (is_atom("objectsize:disk", atom, len))
+   data->info.disk_sizep = >disk_size;
+   else if (is_atom("rest", atom, len))
+   data->split_on_whitespace = 1;
+   else if (is_atom("deltabase", atom, len))
+   data->info.delta_base_sha1 = data->delta_base_oid.hash;
+   else
+   die("unknown format element: %.*s", len, atom);
+}
+
 /*
  * Used to parse format string and sort specifiers
  */
@@ -709,12 +734,18 @@ int verify_ref_format(struct ref_format *format)
if (!ep)
return error(_("malformed format string %s"), sp);
/* sp points at "%(" and ep points at the closing ")" */
-   at = parse_ref_filter_atom(format, valid_atom,
-  ARRAY_SIZE(valid_atom), sp + 2, ep);
-   cp = ep + 1;
 
-   if (skip_prefix(used_atom[at].name, "color:", ))
-   format->need_color_reset_at_eol = !!strcmp(color, 
"reset");
+   if (format->cat_file_data)
+   expand_atom_into_fields(sp + 2, ep - sp - 2,
+   format->cat_file_data);
+   else {
+   at = parse_ref_filter_atom(format, valid_atom,
+  ARRAY_SIZE(valid_atom), sp + 
2, ep);
+   if (skip_prefix(used_atom[at].name, "color:", ))
+   format->need_color_reset_at_eol = 
!!strcmp(color, "reset");
+   }
+
+   cp = ep + 1;
}
if (format->need_color_reset_at_eol && !want_color(format->use_color))
format->need_color_reset_at_eol = 0;
diff --git a/ref-filter.h b/ref-filter.h
index 16d00e4b1bded..97169548939cd 100644
--- a/ref-filter.h
+++ b/ref-filter.h
@@ -119,6 +119,12 @@ struct ref_format {
 
/* Internal state to ref-filter */
int need_color_reset_at_eol;
+
+   /*
+* Helps to move all formatting logic from cat-file to ref-filter,
+* hopefully would be reduced later.
+*/
+   struct expand_data *cat_file_data;
 };
 
 #define REF_FORMAT_INIT { NULL, 0, -1 }

--
https://github.com/git/git/pull/450


[PATCH v2 07/18] cat-file: remove unused code

2018-01-10 Thread Olga Telezhnaya
No further need in mark_query parameter.
All logic related to expand_atom_into_fields is not needed here also,
we are doing that in ref-filter.

Signed-off-by: Olga Telezhnaia 
Mentored-by: Christian Couder 
Mentored by: Jeff King 
---
 builtin/cat-file.c | 25 +
 ref-filter.h   |  6 --
 2 files changed, 1 insertion(+), 30 deletions(-)

diff --git a/builtin/cat-file.c b/builtin/cat-file.c
index 0a3f4a47bf1ae..9055fa3a8b0ae 100644
--- a/builtin/cat-file.c
+++ b/builtin/cat-file.c
@@ -182,25 +182,6 @@ static int is_atom(const char *atom, const char *s, int 
slen)
return alen == slen && !memcmp(atom, s, alen);
 }
 
-static void expand_atom_into_fields(struct strbuf *sb, const char *atom, int 
len,
-   struct expand_data *data)
-{
-   if (is_atom("objectname", atom, len))
-   ; /* do nothing */
-   else if (is_atom("objecttype", atom, len))
-   data->info.typep = >type;
-   else if (is_atom("objectsize", atom, len))
-   data->info.sizep = >size;
-   else if (is_atom("objectsize:disk", atom, len))
-   data->info.disk_sizep = >disk_size;
-   else if (is_atom("rest", atom, len))
-   data->split_on_whitespace = 1;
-   else if (is_atom("deltabase", atom, len))
-   data->info.delta_base_sha1 = data->delta_base_oid.hash;
-   else
-   die("unknown format element: %.*s", len, atom);
-}
-
 static void expand_atom(struct strbuf *sb, const char *atom, int len,
 struct expand_data *data)
 {
@@ -232,11 +213,7 @@ static size_t expand_format(struct strbuf *sb, const char 
*start, void *vdata)
if (!end)
die("format element '%s' does not end in ')'", start);
 
-   if (data->mark_query)
-   expand_atom_into_fields(sb, start + 1, end - start - 1, data);
-   else
-   expand_atom(sb, start + 1, end - start - 1, data);
-
+   expand_atom(sb, start + 1, end - start - 1, data);
return end - start + 1;
 }
 
diff --git a/ref-filter.h b/ref-filter.h
index 97169548939cd..590a60ffe034d 100644
--- a/ref-filter.h
+++ b/ref-filter.h
@@ -80,12 +80,6 @@ struct expand_data {
const char *rest;
struct object_id delta_base_oid;
 
-   /*
-* If mark_query is true, we do not expand anything, but rather
-* just mark the object_info with items we wish to query.
-*/
-   int mark_query;
-
/*
 * Whether to split the input on whitespace before feeding it to
 * get_sha1; this is decided during the mark_query phase based on

--
https://github.com/git/git/pull/450


[PATCH v2 12/18] ref-filter: make populate_value global

2018-01-10 Thread Olga Telezhnaya
Make function global for further using in cat-file.
Also added return value for handling errors.

Signed-off-by: Olga Telezhnaia 
Mentored-by: Christian Couder 
Mentored by: Jeff King 
---
 ref-filter.c | 4 ++--
 ref-filter.h | 3 +++
 2 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/ref-filter.c b/ref-filter.c
index 575c5351d0f79..c15906cb091c7 100644
--- a/ref-filter.c
+++ b/ref-filter.c
@@ -1454,7 +1454,7 @@ static void need_object(struct ref_array_item *ref) {
 /*
  * Parse the object referred by ref, and grab needed value.
  */
-static void populate_value(struct ref_array_item *ref)
+int populate_value(struct ref_array_item *ref)
 {
int i;
 
@@ -1575,7 +1575,7 @@ static void populate_value(struct ref_array_item *ref)
break;
}
}
-   return;
+   return 0;
 }
 
 /*
diff --git a/ref-filter.h b/ref-filter.h
index 9bd36243481b4..6df45c5bd9dcb 100644
--- a/ref-filter.h
+++ b/ref-filter.h
@@ -176,4 +176,7 @@ void setup_ref_filter_porcelain_msg(void);
 void pretty_print_ref(const char *name, const unsigned char *sha1,
  const struct ref_format *format);
 
+/* Fill the values of request and prepare all data for final string creation */
+int populate_value(struct ref_array_item *ref);
+
 #endif /*  REF_FILTER_H  */

--
https://github.com/git/git/pull/450


[PATCH v2 13/18] cat-file: start reusing populate_value

2018-01-10 Thread Olga Telezhnaya
Move logic related to getting object info from cat-file to ref-filter.
It will help to reuse whole formatting logic from ref-filter further.

Signed-off-by: Olga Telezhnaia 
Mentored-by: Christian Couder 
Mentored by: Jeff King 
---
 builtin/cat-file.c | 16 +++-
 ref-filter.c   | 15 +++
 ref-filter.h   |  2 ++
 3 files changed, 20 insertions(+), 13 deletions(-)

diff --git a/builtin/cat-file.c b/builtin/cat-file.c
index 1c92194faaede..e11dbf88e386c 100644
--- a/builtin/cat-file.c
+++ b/builtin/cat-file.c
@@ -284,21 +284,11 @@ static void batch_object_write(const char *obj_name, 
struct batch_options *opt,
struct strbuf buf = STRBUF_INIT;
struct ref_array_item item;
 
-   if (!data->skip_object_info &&
-   sha1_object_info_extended(data->oid.hash, >info,
- OBJECT_INFO_LOOKUP_REPLACE) < 0) {
-   printf("%s missing\n",
-  obj_name ? obj_name : oid_to_hex(>oid));
-   fflush(stdout);
-   return;
-   }
-
item.objectname = data->oid;
-   item.type = data->type;
-   item.size = data->size;
-   item.disk_size = data->disk_size;
item.rest = data->rest;
-   item.delta_base_oid = data->delta_base_oid;
+   item.start_of_request = obj_name;
+
+   if (populate_value()) return;
 
strbuf_expand(, opt->format->format, expand_format, );
strbuf_addch(, '\n');
diff --git a/ref-filter.c b/ref-filter.c
index c15906cb091c7..35e16cec6d862 100644
--- a/ref-filter.c
+++ b/ref-filter.c
@@ -1467,6 +1467,21 @@ int populate_value(struct ref_array_item *ref)
ref->symref = "";
}
 
+   if (cat_file_info) {
+   if (!cat_file_info->skip_object_info &&
+   sha1_object_info_extended(ref->objectname.hash, 
_file_info->info,
+ OBJECT_INFO_LOOKUP_REPLACE) < 0) {
+   const char *e = ref->start_of_request;
+   printf("%s missing\n", e ? e : 
oid_to_hex(>objectname));
+   fflush(stdout);
+   return -1;
+   }
+   ref->type = cat_file_info->type;
+   ref->size = cat_file_info->size;
+   ref->disk_size = cat_file_info->disk_size;
+   ref->delta_base_oid = cat_file_info->delta_base_oid;
+   }
+
/* Fill in specials first */
for (i = 0; i < used_atom_cnt; i++) {
struct used_atom *atom = _atom[i];
diff --git a/ref-filter.h b/ref-filter.h
index 6df45c5bd9dcb..0c7253913735b 100644
--- a/ref-filter.h
+++ b/ref-filter.h
@@ -45,6 +45,8 @@ struct ref_array_item {
off_t disk_size;
const char *rest;
struct object_id delta_base_oid;
+   /* Need it for better explanation in error log. */
+   const char *start_of_request;
char refname[FLEX_ARRAY];
 };
 

--
https://github.com/git/git/pull/450


[PATCH v2 09/18] cat-file: simplify expand_atom function

2018-01-10 Thread Olga Telezhnaya
Not sure, but looks like there is no need in that checking.
There is a checking before whether it is null and we die in such case.

Signed-off-by: Olga Telezhnaia 
Mentored-by: Christian Couder 
Mentored by: Jeff King 
---
 builtin/cat-file.c | 7 +++
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/builtin/cat-file.c b/builtin/cat-file.c
index 9055fa3a8b0ae..dd43457c0ad7e 100644
--- a/builtin/cat-file.c
+++ b/builtin/cat-file.c
@@ -193,10 +193,9 @@ static void expand_atom(struct strbuf *sb, const char 
*atom, int len,
strbuf_addf(sb, "%lu", data->size);
else if (is_atom("objectsize:disk", atom, len))
strbuf_addf(sb, "%"PRIuMAX, (uintmax_t)data->disk_size);
-   else if (is_atom("rest", atom, len)) {
-   if (data->rest)
-   strbuf_addstr(sb, data->rest);
-   } else if (is_atom("deltabase", atom, len))
+   else if (is_atom("rest", atom, len))
+   strbuf_addstr(sb, data->rest);
+   else if (is_atom("deltabase", atom, len))
strbuf_addstr(sb, oid_to_hex(>delta_base_oid));
else
die("unknown format element: %.*s", len, atom);

--
https://github.com/git/git/pull/450


[PATCH v2 11/18] cat-file: start use ref_array_item struct

2018-01-10 Thread Olga Telezhnaya
Moving from using expand_data to ref_array_item structure.
That helps us to reuse functions from ref-filter easier.

Signed-off-by: Olga Telezhnaia 
Mentored-by: Christian Couder 
Mentored by: Jeff King 
---
 builtin/cat-file.c | 30 +++---
 ref-filter.h   |  5 +
 2 files changed, 24 insertions(+), 11 deletions(-)

diff --git a/builtin/cat-file.c b/builtin/cat-file.c
index 1f331559e55c7..1c92194faaede 100644
--- a/builtin/cat-file.c
+++ b/builtin/cat-file.c
@@ -183,26 +183,26 @@ static int is_atom(const char *atom, const char *s, int 
slen)
 }
 
 static void expand_atom(struct strbuf *sb, const char *atom, int len,
-struct expand_data *data)
+struct ref_array_item *item)
 {
if (is_atom("objectname", atom, len))
-   strbuf_addstr(sb, oid_to_hex(>oid));
+   strbuf_addstr(sb, oid_to_hex(>objectname));
else if (is_atom("objecttype", atom, len))
-   strbuf_addstr(sb, typename(data->type));
+   strbuf_addstr(sb, typename(item->type));
else if (is_atom("objectsize", atom, len))
-   strbuf_addf(sb, "%lu", data->size);
+   strbuf_addf(sb, "%lu", item->size);
else if (is_atom("objectsize:disk", atom, len))
-   strbuf_addf(sb, "%"PRIuMAX, (uintmax_t)data->disk_size);
+   strbuf_addf(sb, "%"PRIuMAX, (uintmax_t)item->disk_size);
else if (is_atom("rest", atom, len))
-   strbuf_addstr(sb, data->rest);
+   strbuf_addstr(sb, item->rest);
else if (is_atom("deltabase", atom, len))
-   strbuf_addstr(sb, oid_to_hex(>delta_base_oid));
+   strbuf_addstr(sb, oid_to_hex(>delta_base_oid));
 }
 
-static size_t expand_format(struct strbuf *sb, const char *start, void *vdata)
+static size_t expand_format(struct strbuf *sb, const char *start, void *data)
 {
const char *end;
-   struct expand_data *data = vdata;
+   struct ref_array_item *item = data;
 
if (*start != '(')
return 0;
@@ -210,7 +210,7 @@ static size_t expand_format(struct strbuf *sb, const char 
*start, void *vdata)
if (!end)
die("format element '%s' does not end in ')'", start);
 
-   expand_atom(sb, start + 1, end - start - 1, data);
+   expand_atom(sb, start + 1, end - start - 1, item);
return end - start + 1;
 }
 
@@ -282,6 +282,7 @@ static void batch_object_write(const char *obj_name, struct 
batch_options *opt,
   struct expand_data *data)
 {
struct strbuf buf = STRBUF_INIT;
+   struct ref_array_item item;
 
if (!data->skip_object_info &&
sha1_object_info_extended(data->oid.hash, >info,
@@ -292,7 +293,14 @@ static void batch_object_write(const char *obj_name, 
struct batch_options *opt,
return;
}
 
-   strbuf_expand(, opt->format->format, expand_format, data);
+   item.objectname = data->oid;
+   item.type = data->type;
+   item.size = data->size;
+   item.disk_size = data->disk_size;
+   item.rest = data->rest;
+   item.delta_base_oid = data->delta_base_oid;
+
+   strbuf_expand(, opt->format->format, expand_format, );
strbuf_addch(, '\n');
batch_write(opt, buf.buf, buf.len);
strbuf_release();
diff --git a/ref-filter.h b/ref-filter.h
index 590a60ffe034d..9bd36243481b4 100644
--- a/ref-filter.h
+++ b/ref-filter.h
@@ -40,6 +40,11 @@ struct ref_array_item {
const char *symref;
struct commit *commit;
struct atom_value *value;
+   enum object_type type;
+   unsigned long size;
+   off_t disk_size;
+   const char *rest;
+   struct object_id delta_base_oid;
char refname[FLEX_ARRAY];
 };
 

--
https://github.com/git/git/pull/450


[PATCH v2 03/18] ref-filter: make valid_atom as function parameter

2018-01-10 Thread Olga Telezhnaya
Make valid_atom as a function parameter,
there could be another variable further.
Need that for further reusing of formatting logic in cat-file.c.

We do not need to allow users to pass their own valid_atom variable in
global functions like verify_ref_format because in the end we want to
have same set of valid atoms for all commands. But, as a first step
of migrating, I create further another version of valid_atom
for cat-file.

Signed-off-by: Olga Telezhnaia 
Mentored-by: Christian Couder 
Mentored by: Jeff King 
---
 ref-filter.c | 17 +++--
 1 file changed, 11 insertions(+), 6 deletions(-)

diff --git a/ref-filter.c b/ref-filter.c
index 3f9161707e66b..32b7e918bca75 100644
--- a/ref-filter.c
+++ b/ref-filter.c
@@ -325,7 +325,7 @@ static void head_atom_parser(const struct ref_format 
*format, struct used_atom *
atom->u.head = resolve_refdup("HEAD", RESOLVE_REF_READING, NULL, NULL);
 }
 
-static struct {
+static struct valid_atom {
const char *name;
cmp_type cmp_type;
void (*parser)(const struct ref_format *format, struct used_atom *atom, 
const char *arg);
@@ -396,6 +396,7 @@ struct atom_value {
  * Used to parse format string and sort specifiers
  */
 static int parse_ref_filter_atom(const struct ref_format *format,
+const struct valid_atom *valid_atom, int 
n_atoms,
 const char *atom, const char *ep)
 {
const char *sp;
@@ -425,13 +426,13 @@ static int parse_ref_filter_atom(const struct ref_format 
*format,
atom_len = (arg ? arg : ep) - sp;
 
/* Is the atom a valid one? */
-   for (i = 0; i < ARRAY_SIZE(valid_atom); i++) {
+   for (i = 0; i < n_atoms; i++) {
int len = strlen(valid_atom[i].name);
if (len == atom_len && !memcmp(valid_atom[i].name, sp, len))
break;
}
 
-   if (ARRAY_SIZE(valid_atom) <= i)
+   if (n_atoms <= i)
die(_("unknown field name: %.*s"), (int)(ep-atom), atom);
 
/* Add it in, including the deref prefix */
@@ -708,7 +709,8 @@ int verify_ref_format(struct ref_format *format)
if (!ep)
return error(_("malformed format string %s"), sp);
/* sp points at "%(" and ep points at the closing ")" */
-   at = parse_ref_filter_atom(format, sp + 2, ep);
+   at = parse_ref_filter_atom(format, valid_atom,
+  ARRAY_SIZE(valid_atom), sp + 2, ep);
cp = ep + 1;
 
if (skip_prefix(used_atom[at].name, "color:", ))
@@ -2139,7 +2141,9 @@ void format_ref_array_item(struct ref_array_item *info,
if (cp < sp)
append_literal(cp, sp, );
get_ref_atom_value(info,
-  parse_ref_filter_atom(format, sp + 2, ep),
+  parse_ref_filter_atom(format, valid_atom,
+ARRAY_SIZE(valid_atom),
+sp + 2, ep),
   );
atomv->handler(atomv, );
}
@@ -2187,7 +2191,8 @@ static int parse_sorting_atom(const char *atom)
 */
struct ref_format dummy = REF_FORMAT_INIT;
const char *end = atom + strlen(atom);
-   return parse_ref_filter_atom(, atom, end);
+   return parse_ref_filter_atom(, valid_atom,
+ARRAY_SIZE(valid_atom), atom, end);
 }
 
 /*  If no sorting option is given, use refname to sort as default */

--
https://github.com/git/git/pull/450


[PATCH v2 06/18] ref-filter: reuse parse_ref_filter_atom

2018-01-10 Thread Olga Telezhnaya
Continue migrating formatting logic from cat-file to ref-filter.
Reuse parse_ref_filter_atom for unifying all processes in ref-filter
and further reducing of expand_atom_into_fields function.

Signed-off-by: Olga Telezhnaia 
Mentored-by: Christian Couder 
Mentored by: Jeff King 
---
 ref-filter.c | 38 +++---
 1 file changed, 27 insertions(+), 11 deletions(-)

diff --git a/ref-filter.c b/ref-filter.c
index 6ca4a671086ee..bb09875e2dbf4 100644
--- a/ref-filter.c
+++ b/ref-filter.c
@@ -100,6 +100,7 @@ static struct used_atom {
} u;
 } *used_atom;
 static int used_atom_cnt, need_tagged, need_symref;
+struct expand_data *cat_file_info;
 
 static void color_atom_parser(const struct ref_format *format, struct 
used_atom *atom, const char *color_value)
 {
@@ -251,6 +252,16 @@ static void objectname_atom_parser(const struct ref_format 
*format, struct used_
die(_("unrecognized %%(objectname) argument: %s"), arg);
 }
 
+static void objectsize_atom_parser(const struct ref_format *format, struct 
used_atom *atom, const char *arg)
+{
+   if (!arg)
+   ; /* default to normal object size */
+   else if (!strcmp(arg, "disk"))
+   cat_file_info->info.disk_sizep = _file_info->disk_size;
+   else
+   die(_("urecognized %%(objectsize) argument: %s"), arg);
+}
+
 static void refname_atom_parser(const struct ref_format *format, struct 
used_atom *atom, const char *arg)
 {
refname_atom_parser_internal(>u.refname, arg, atom->name);
@@ -371,6 +382,14 @@ static struct valid_atom {
{ "else" },
 };
 
+static struct valid_atom valid_cat_file_atom[] = {
+   { "objectname" },
+   { "objecttype" },
+   { "objectsize", FIELD_ULONG, objectsize_atom_parser },
+   { "rest" },
+   { "deltabase" },
+};
+
 #define REF_FORMATTING_STATE_INIT  { 0, NULL }
 
 struct ref_formatting_stack {
@@ -401,20 +420,14 @@ static int is_atom(const char *atom, const char *s, int 
slen)
 static void expand_atom_into_fields(const char *atom, int len,
struct expand_data *data)
 {
-   if (is_atom("objectname", atom, len))
-   ; /* do nothing */
-   else if (is_atom("objecttype", atom, len))
+   if (is_atom("objecttype", atom, len))
data->info.typep = >type;
else if (is_atom("objectsize", atom, len))
data->info.sizep = >size;
-   else if (is_atom("objectsize:disk", atom, len))
-   data->info.disk_sizep = >disk_size;
else if (is_atom("rest", atom, len))
data->split_on_whitespace = 1;
else if (is_atom("deltabase", atom, len))
data->info.delta_base_sha1 = data->delta_base_oid.hash;
-   else
-   die("unknown format element: %.*s", len, atom);
 }
 
 /*
@@ -483,6 +496,8 @@ static int parse_ref_filter_atom(const struct ref_format 
*format,
need_tagged = 1;
if (!strcmp(valid_atom[i].name, "symref"))
need_symref = 1;
+   if (cat_file_info)
+   expand_atom_into_fields(atom, atom_len, cat_file_info);
return at;
 }
 
@@ -726,6 +741,7 @@ int verify_ref_format(struct ref_format *format)
 {
const char *cp, *sp;
 
+   cat_file_info = format->cat_file_data;
format->need_color_reset_at_eol = 0;
for (cp = format->format; *cp && (sp = find_next(cp)); ) {
const char *color, *ep = strchr(sp, ')');
@@ -735,10 +751,10 @@ int verify_ref_format(struct ref_format *format)
return error(_("malformed format string %s"), sp);
/* sp points at "%(" and ep points at the closing ")" */
 
-   if (format->cat_file_data)
-   expand_atom_into_fields(sp + 2, ep - sp - 2,
-   format->cat_file_data);
-   else {
+   if (format->cat_file_data) {
+   at = parse_ref_filter_atom(format, valid_cat_file_atom,
+  
ARRAY_SIZE(valid_cat_file_atom), sp + 2, ep);
+   } else {
at = parse_ref_filter_atom(format, valid_atom,
   ARRAY_SIZE(valid_atom), sp + 
2, ep);
if (skip_prefix(used_atom[at].name, "color:", ))

--
https://github.com/git/git/pull/450


[PATCH v2 04/18] cat-file: move struct expand_data into ref-filter

2018-01-10 Thread Olga Telezhnaya
Need that for further reusing of formatting logic in cat-file.
Have plans to get rid of using expand_data in cat-file at all,
and use it only in ref-filter for collecting, formatting and printing
needed data.

Signed-off-by: Olga Telezhnaia 
Mentored-by: Christian Couder 
Mentored by: Jeff King 
---
 builtin/cat-file.c | 36 
 ref-filter.h   | 36 
 2 files changed, 36 insertions(+), 36 deletions(-)

diff --git a/builtin/cat-file.c b/builtin/cat-file.c
index 7655a9a726773..7fd5b960ad698 100644
--- a/builtin/cat-file.c
+++ b/builtin/cat-file.c
@@ -176,42 +176,6 @@ static int cat_one_file(int opt, const char *exp_type, 
const char *obj_name,
return 0;
 }
 
-struct expand_data {
-   struct object_id oid;
-   enum object_type type;
-   unsigned long size;
-   off_t disk_size;
-   const char *rest;
-   struct object_id delta_base_oid;
-
-   /*
-* If mark_query is true, we do not expand anything, but rather
-* just mark the object_info with items we wish to query.
-*/
-   int mark_query;
-
-   /*
-* Whether to split the input on whitespace before feeding it to
-* get_sha1; this is decided during the mark_query phase based on
-* whether we have a %(rest) token in our format.
-*/
-   int split_on_whitespace;
-
-   /*
-* After a mark_query run, this object_info is set up to be
-* passed to sha1_object_info_extended. It will point to the data
-* elements above, so you can retrieve the response from there.
-*/
-   struct object_info info;
-
-   /*
-* This flag will be true if the requested batch format and options
-* don't require us to call sha1_object_info, which can then be
-* optimized out.
-*/
-   unsigned skip_object_info : 1;
-};
-
 static int is_atom(const char *atom, const char *s, int slen)
 {
int alen = strlen(atom);
diff --git a/ref-filter.h b/ref-filter.h
index 0d98342b34319..16d00e4b1bded 100644
--- a/ref-filter.h
+++ b/ref-filter.h
@@ -72,6 +72,42 @@ struct ref_filter {
verbose;
 };
 
+struct expand_data {
+   struct object_id oid;
+   enum object_type type;
+   unsigned long size;
+   off_t disk_size;
+   const char *rest;
+   struct object_id delta_base_oid;
+
+   /*
+* If mark_query is true, we do not expand anything, but rather
+* just mark the object_info with items we wish to query.
+*/
+   int mark_query;
+
+   /*
+* Whether to split the input on whitespace before feeding it to
+* get_sha1; this is decided during the mark_query phase based on
+* whether we have a %(rest) token in our format.
+*/
+   int split_on_whitespace;
+
+   /*
+* After a mark_query run, this object_info is set up to be
+* passed to sha1_object_info_extended. It will point to the data
+* elements above, so you can retrieve the response from there.
+*/
+   struct object_info info;
+
+   /*
+* This flag will be true if the requested batch format and options
+* don't require us to call sha1_object_info, which can then be
+* optimized out.
+*/
+   unsigned skip_object_info : 1;
+};
+
 struct ref_format {
/*
 * Set these to define the format; make sure you call

--
https://github.com/git/git/pull/450


[PATCH v2 14/18] ref-filter: get rid of expand_atom_into_fields

2018-01-10 Thread Olga Telezhnaya
Remove expand_atom_into_fields function and create same logic
in terms of ref-filter style.

Signed-off-by: Olga Telezhnaia 
Mentored-by: Christian Couder 
Mentored by: Jeff King 
---
 ref-filter.c | 45 +
 1 file changed, 21 insertions(+), 24 deletions(-)

diff --git a/ref-filter.c b/ref-filter.c
index 35e16cec6d862..93248ce18152f 100644
--- a/ref-filter.c
+++ b/ref-filter.c
@@ -255,13 +255,29 @@ static void objectname_atom_parser(const struct 
ref_format *format, struct used_
 static void objectsize_atom_parser(const struct ref_format *format, struct 
used_atom *atom, const char *arg)
 {
if (!arg)
-   ; /* default to normal object size */
+   cat_file_info->info.sizep = _file_info->size;
else if (!strcmp(arg, "disk"))
cat_file_info->info.disk_sizep = _file_info->disk_size;
else
die(_("urecognized %%(objectsize) argument: %s"), arg);
 }
 
+static void objecttype_atom_parser(const struct ref_format *format, struct 
used_atom *atom, const char *arg)
+{
+   if (!arg)
+   cat_file_info->info.typep = _file_info->type;
+   else
+   die(_("urecognized %%(objecttype) argument: %s"), arg);
+}
+
+static void deltabase_atom_parser(const struct ref_format *format, struct 
used_atom *atom, const char *arg)
+{
+   if (!arg)
+   cat_file_info->info.delta_base_sha1 = 
cat_file_info->delta_base_oid.hash;
+   else
+   die(_("urecognized %%(deltabase) argument: %s"), arg);
+}
+
 static void refname_atom_parser(const struct ref_format *format, struct 
used_atom *atom, const char *arg)
 {
refname_atom_parser_internal(>u.refname, arg, atom->name);
@@ -384,10 +400,10 @@ static struct valid_atom {
 
 static struct valid_atom valid_cat_file_atom[] = {
{ "objectname" },
-   { "objecttype" },
+   { "objecttype", FIELD_STR, objecttype_atom_parser },
{ "objectsize", FIELD_ULONG, objectsize_atom_parser },
{ "rest" },
-   { "deltabase" },
+   { "deltabase", FIELD_STR, deltabase_atom_parser },
 };
 
 #define REF_FORMATTING_STATE_INIT  { 0, NULL }
@@ -411,25 +427,6 @@ struct atom_value {
struct used_atom *atom;
 };
 
-static int is_atom(const char *atom, const char *s, int slen)
-{
-   int alen = strlen(atom);
-   return alen == slen && !memcmp(atom, s, alen);
-}
-
-static void expand_atom_into_fields(const char *atom, int len,
-   struct expand_data *data)
-{
-   if (is_atom("objecttype", atom, len))
-   data->info.typep = >type;
-   else if (is_atom("objectsize", atom, len))
-   data->info.sizep = >size;
-   else if (is_atom("rest", atom, len))
-   data->split_on_whitespace = 1;
-   else if (is_atom("deltabase", atom, len))
-   data->info.delta_base_sha1 = data->delta_base_oid.hash;
-}
-
 /*
  * Used to parse format string and sort specifiers
  */
@@ -496,8 +493,8 @@ static int parse_ref_filter_atom(const struct ref_format 
*format,
need_tagged = 1;
if (!strcmp(valid_atom[i].name, "symref"))
need_symref = 1;
-   if (cat_file_info)
-   expand_atom_into_fields(atom, atom_len, cat_file_info);
+   if (cat_file_info && !strcmp(valid_atoms[i].name, "rest"))
+   cat_file_info->split_on_whitespace = 1;
return at;
 }
 

--
https://github.com/git/git/pull/450


[PATCH v2 16/18] ref_format: add split_on_whitespace flag

2018-01-10 Thread Olga Telezhnaya
Add flag to ref_format struct so that we could pass needed info
to cat-file.

Signed-off-by: Olga Telezhnaia 
Mentored-by: Christian Couder 
Mentored by: Jeff King 
---
 builtin/cat-file.c | 1 +
 ref-filter.c   | 4 ++--
 ref-filter.h   | 1 +
 3 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/builtin/cat-file.c b/builtin/cat-file.c
index 289912ab1f858..5aac10b9808ff 100644
--- a/builtin/cat-file.c
+++ b/builtin/cat-file.c
@@ -394,6 +394,7 @@ static int batch_objects(struct batch_options *opt)
memset(, 0, sizeof(data));
opt->format->cat_file_data = 
opt->format->is_cat = 1;
+   opt->format->split_on_whitespace = _on_whitespace;
verify_ref_format(opt->format);
if (opt->cmdmode)
data.split_on_whitespace = 1;
diff --git a/ref-filter.c b/ref-filter.c
index 2c955e90bb4c9..0fb33198fb450 100644
--- a/ref-filter.c
+++ b/ref-filter.c
@@ -494,8 +494,8 @@ static int parse_ref_filter_atom(const struct ref_format 
*format,
need_tagged = 1;
if (!strcmp(valid_atom[i].name, "symref"))
need_symref = 1;
-   if (is_cat && !strcmp(valid_atoms[i].name, "rest"))
-   cat_file_info->split_on_whitespace = 1;
+   if (!strcmp(valid_atom[i].name, "rest"))
+   *format->split_on_whitespace = 1;
return at;
 }
 
diff --git a/ref-filter.h b/ref-filter.h
index 12a938b0aa6a3..aaf1790e43e62 100644
--- a/ref-filter.h
+++ b/ref-filter.h
@@ -127,6 +127,7 @@ struct ref_format {
 */
struct expand_data *cat_file_data;
int is_cat;
+   int *split_on_whitespace;
 };
 
 #define REF_FORMAT_INIT { NULL, 0, -1 }

--
https://github.com/git/git/pull/450


[PATCH v2 08/18] ref-filter: get rid of goto

2018-01-10 Thread Olga Telezhnaya
Get rid of goto command in ref-filter for better readability.

Signed-off-by: Olga Telezhnaia 
Mentored-by: Christian Couder 
Mentored by: Jeff King 
---
 ref-filter.c | 103 ++-
 1 file changed, 53 insertions(+), 50 deletions(-)

diff --git a/ref-filter.c b/ref-filter.c
index bb09875e2dbf4..575c5351d0f79 100644
--- a/ref-filter.c
+++ b/ref-filter.c
@@ -1403,16 +1403,60 @@ static const char *get_refname(struct used_atom *atom, 
struct ref_array_item *re
return show_ref(>u.refname, ref->refname);
 }
 
+static void need_object(struct ref_array_item *ref) {
+   struct object *obj;
+   const struct object_id *tagged;
+   unsigned long size;
+   int eaten;
+   void *buf = get_obj(>objectname, , , );
+   if (!buf)
+   die(_("missing object %s for %s"),
+   oid_to_hex(>objectname), ref->refname);
+   if (!obj)
+   die(_("parse_object_buffer failed on %s for %s"),
+   oid_to_hex(>objectname), ref->refname);
+
+   grab_values(ref->value, 0, obj, buf, size);
+   if (!eaten)
+   free(buf);
+
+   /*
+* If there is no atom that wants to know about tagged
+* object, we are done.
+*/
+   if (!need_tagged || (obj->type != OBJ_TAG))
+   return;
+
+   /*
+* If it is a tag object, see if we use a value that derefs
+* the object, and if we do grab the object it refers to.
+*/
+   tagged = &((struct tag *)obj)->tagged->oid;
+
+   /*
+* NEEDSWORK: This derefs tag only once, which
+* is good to deal with chains of trust, but
+* is not consistent with what deref_tag() does
+* which peels the onion to the core.
+*/
+   buf = get_obj(tagged, , , );
+   if (!buf)
+   die(_("missing object %s for %s"),
+   oid_to_hex(tagged), ref->refname);
+   if (!obj)
+   die(_("parse_object_buffer failed on %s for %s"),
+   oid_to_hex(tagged), ref->refname);
+   grab_values(ref->value, 1, obj, buf, size);
+   if (!eaten)
+   free(buf);
+}
+
 /*
  * Parse the object referred by ref, and grab needed value.
  */
 static void populate_value(struct ref_array_item *ref)
 {
-   void *buf;
-   struct object *obj;
-   int eaten, i;
-   unsigned long size;
-   const struct object_id *tagged;
+   int i;
 
ref->value = xcalloc(used_atom_cnt, sizeof(struct atom_value));
 
@@ -1526,53 +1570,12 @@ static void populate_value(struct ref_array_item *ref)
 
for (i = 0; i < used_atom_cnt; i++) {
struct atom_value *v = >value[i];
-   if (v->s == NULL)
-   goto need_obj;
+   if (v->s == NULL) {
+   need_object(ref);
+   break;
+   }
}
return;
-
- need_obj:
-   buf = get_obj(>objectname, , , );
-   if (!buf)
-   die(_("missing object %s for %s"),
-   oid_to_hex(>objectname), ref->refname);
-   if (!obj)
-   die(_("parse_object_buffer failed on %s for %s"),
-   oid_to_hex(>objectname), ref->refname);
-
-   grab_values(ref->value, 0, obj, buf, size);
-   if (!eaten)
-   free(buf);
-
-   /*
-* If there is no atom that wants to know about tagged
-* object, we are done.
-*/
-   if (!need_tagged || (obj->type != OBJ_TAG))
-   return;
-
-   /*
-* If it is a tag object, see if we use a value that derefs
-* the object, and if we do grab the object it refers to.
-*/
-   tagged = &((struct tag *)obj)->tagged->oid;
-
-   /*
-* NEEDSWORK: This derefs tag only once, which
-* is good to deal with chains of trust, but
-* is not consistent with what deref_tag() does
-* which peels the onion to the core.
-*/
-   buf = get_obj(tagged, , , );
-   if (!buf)
-   die(_("missing object %s for %s"),
-   oid_to_hex(tagged), ref->refname);
-   if (!obj)
-   die(_("parse_object_buffer failed on %s for %s"),
-   oid_to_hex(tagged), ref->refname);
-   grab_values(ref->value, 1, obj, buf, size);
-   if (!eaten)
-   free(buf);
 }
 
 /*

--
https://github.com/git/git/pull/450


[PATCH v2 02/18] cat-file: reuse struct ref_format

2018-01-10 Thread Olga Telezhnaya
Start using ref_format struct instead of simple char*.
Need that for further reusing of formatting logic from ref-filter.

Signed-off-by: Olga Telezhnaia 
Mentored-by: Christian Couder 
Mentored by: Jeff King 
---
 builtin/cat-file.c | 16 +---
 1 file changed, 9 insertions(+), 7 deletions(-)

diff --git a/builtin/cat-file.c b/builtin/cat-file.c
index f783b39b9bd5c..7655a9a726773 100644
--- a/builtin/cat-file.c
+++ b/builtin/cat-file.c
@@ -13,15 +13,16 @@
 #include "tree-walk.h"
 #include "sha1-array.h"
 #include "packfile.h"
+#include "ref-filter.h"
 
 struct batch_options {
+   struct ref_format *format;
int enabled;
int follow_symlinks;
int print_contents;
int buffer_output;
int all_objects;
int cmdmode; /* may be 'w' or 'c' for --filters or --textconv */
-   const char *format;
 };
 
 static const char *force_path;
@@ -353,7 +354,7 @@ static void batch_object_write(const char *obj_name, struct 
batch_options *opt,
return;
}
 
-   strbuf_expand(, opt->format, expand_format, data);
+   strbuf_expand(, opt->format->format, expand_format, data);
strbuf_addch(, '\n');
batch_write(opt, buf.buf, buf.len);
strbuf_release();
@@ -446,8 +447,8 @@ static int batch_objects(struct batch_options *opt)
int save_warning;
int retval = 0;
 
-   if (!opt->format)
-   opt->format = "%(objectname) %(objecttype) %(objectsize)";
+   if (!opt->format->format)
+   opt->format->format = "%(objectname) %(objecttype) 
%(objectsize)";
 
/*
 * Expand once with our special mark_query flag, which will prime the
@@ -456,7 +457,7 @@ static int batch_objects(struct batch_options *opt)
 */
memset(, 0, sizeof(data));
data.mark_query = 1;
-   strbuf_expand(, opt->format, expand_format, );
+   strbuf_expand(, opt->format->format, expand_format, );
data.mark_query = 0;
if (opt->cmdmode)
data.split_on_whitespace = 1;
@@ -548,7 +549,7 @@ static int batch_option_callback(const struct option *opt,
 
bo->enabled = 1;
bo->print_contents = !strcmp(opt->long_name, "batch");
-   bo->format = arg;
+   bo->format->format = arg;
 
return 0;
 }
@@ -557,7 +558,8 @@ int cmd_cat_file(int argc, const char **argv, const char 
*prefix)
 {
int opt = 0;
const char *exp_type = NULL, *obj_name = NULL;
-   struct batch_options batch = {0};
+   struct ref_format format = REF_FORMAT_INIT;
+   struct batch_options batch = {};
int unknown_type = 0;
 
const struct option options[] = {

--
https://github.com/git/git/pull/450


[PATCH v2 18/18] ref-filter: make cat_file_info independent

2018-01-10 Thread Olga Telezhnaya
Remove connection between expand_data variable
in cat-file and in ref-filter.
It will help further to get rid of using expand_data in cat-file.

Signed-off-by: Olga Telezhnaia 
Mentored-by: Christian Couder 
Mentored by: Jeff King 
---
 builtin/cat-file.c |  2 +-
 ref-filter.c   | 28 ++--
 ref-filter.h   |  1 -
 3 files changed, 15 insertions(+), 16 deletions(-)

diff --git a/builtin/cat-file.c b/builtin/cat-file.c
index 19cee0d22fabe..ffa8e61213e36 100644
--- a/builtin/cat-file.c
+++ b/builtin/cat-file.c
@@ -289,6 +289,7 @@ static void batch_object_write(const char *obj_name, struct 
batch_options *opt,
item.start_of_request = obj_name;
 
if (populate_value()) return;
+   data->type = item.type;
 
strbuf_expand(, opt->format->format, expand_format, );
strbuf_addch(, '\n');
@@ -392,7 +393,6 @@ static int batch_objects(struct batch_options *opt)
 * object.
 */
memset(, 0, sizeof(data));
-   opt->format->cat_file_data = 
opt->format->is_cat = 1;
opt->format->split_on_whitespace = _on_whitespace;
opt->format->all_objects = opt->all_objects;
diff --git a/ref-filter.c b/ref-filter.c
index 83bacdd8bdd78..aee6be32f53ef 100644
--- a/ref-filter.c
+++ b/ref-filter.c
@@ -100,7 +100,7 @@ static struct used_atom {
} u;
 } *used_atom;
 static int used_atom_cnt, need_tagged, need_symref;
-struct expand_data *cat_file_info;
+struct expand_data cat_file_info;
 static int is_cat = 0;
 
 static void color_atom_parser(const struct ref_format *format, struct 
used_atom *atom, const char *color_value)
@@ -256,9 +256,9 @@ static void objectname_atom_parser(const struct ref_format 
*format, struct used_
 static void objectsize_atom_parser(const struct ref_format *format, struct 
used_atom *atom, const char *arg)
 {
if (!arg)
-   cat_file_info->info.sizep = _file_info->size;
+   cat_file_info.info.sizep = _file_info.size;
else if (!strcmp(arg, "disk"))
-   cat_file_info->info.disk_sizep = _file_info->disk_size;
+   cat_file_info.info.disk_sizep = _file_info.disk_size;
else
die(_("urecognized %%(objectsize) argument: %s"), arg);
 }
@@ -266,7 +266,7 @@ static void objectsize_atom_parser(const struct ref_format 
*format, struct used_
 static void objecttype_atom_parser(const struct ref_format *format, struct 
used_atom *atom, const char *arg)
 {
if (!arg)
-   cat_file_info->info.typep = _file_info->type;
+   cat_file_info.info.typep = _file_info.type;
else
die(_("urecognized %%(objecttype) argument: %s"), arg);
 }
@@ -274,7 +274,7 @@ static void objecttype_atom_parser(const struct ref_format 
*format, struct used_
 static void deltabase_atom_parser(const struct ref_format *format, struct 
used_atom *atom, const char *arg)
 {
if (!arg)
-   cat_file_info->info.delta_base_sha1 = 
cat_file_info->delta_base_oid.hash;
+   cat_file_info.info.delta_base_sha1 = 
cat_file_info.delta_base_oid.hash;
else
die(_("urecognized %%(deltabase) argument: %s"), arg);
 }
@@ -739,7 +739,6 @@ int verify_ref_format(struct ref_format *format)
 {
const char *cp, *sp;
 
-   cat_file_info = format->cat_file_data;
is_cat = format->is_cat;
format->need_color_reset_at_eol = 0;
for (cp = format->format; *cp && (sp = find_next(cp)); ) {
@@ -766,8 +765,8 @@ int verify_ref_format(struct ref_format *format)
format->need_color_reset_at_eol = 0;
if (is_cat && format->all_objects) {
struct object_info empty = OBJECT_INFO_INIT;
-   if (!memcmp(_file_info->info, , sizeof(empty)))
-   cat_file_info->skip_object_info = 1;
+   if (!memcmp(_file_info.info, , sizeof(empty)))
+   cat_file_info.skip_object_info = 1;
}
return 0;
 }
@@ -1472,18 +1471,19 @@ int populate_value(struct ref_array_item *ref)
}
 
if (is_cat) {
-   if (!cat_file_info->skip_object_info &&
-   sha1_object_info_extended(ref->objectname.hash, 
_file_info->info,
+   if (!cat_file_info.info.typep) cat_file_info.info.typep = 
_file_info.type;
+   if (!cat_file_info.skip_object_info &&
+   sha1_object_info_extended(ref->objectname.hash, 
_file_info.info,
  OBJECT_INFO_LOOKUP_REPLACE) < 0) {
const char *e = ref->start_of_request;
printf("%s missing\n", e ? e : 
oid_to_hex(>objectname));
fflush(stdout);
return -1;
}
-   ref->type = cat_file_info->type;
-   ref->size = cat_file_info->size;
-   

[PATCH v2 01/18] cat-file: split expand_atom into 2 functions

2018-01-10 Thread Olga Telezhnaya
Split expand_atom function into 2 different functions,
expand_atom_into_fields prepares variable for further filling,
(new) expand_atom creates resulting string.
Need that for further reusing of formatting logic from ref-filter.

Signed-off-by: Olga Telezhnaia 
Mentored-by: Christian Couder 
Mentored by: Jeff King 
---
 builtin/cat-file.c | 73 +-
 1 file changed, 39 insertions(+), 34 deletions(-)

diff --git a/builtin/cat-file.c b/builtin/cat-file.c
index f5fa4fd75af26..f783b39b9bd5c 100644
--- a/builtin/cat-file.c
+++ b/builtin/cat-file.c
@@ -217,47 +217,49 @@ static int is_atom(const char *atom, const char *s, int 
slen)
return alen == slen && !memcmp(atom, s, alen);
 }
 
-static void expand_atom(struct strbuf *sb, const char *atom, int len,
-   void *vdata)
+static void expand_atom_into_fields(struct strbuf *sb, const char *atom, int 
len,
+   struct expand_data *data)
 {
-   struct expand_data *data = vdata;
+   if (is_atom("objectname", atom, len))
+   ; /* do nothing */
+   else if (is_atom("objecttype", atom, len))
+   data->info.typep = >type;
+   else if (is_atom("objectsize", atom, len))
+   data->info.sizep = >size;
+   else if (is_atom("objectsize:disk", atom, len))
+   data->info.disk_sizep = >disk_size;
+   else if (is_atom("rest", atom, len))
+   data->split_on_whitespace = 1;
+   else if (is_atom("deltabase", atom, len))
+   data->info.delta_base_sha1 = data->delta_base_oid.hash;
+   else
+   die("unknown format element: %.*s", len, atom);
+}
 
-   if (is_atom("objectname", atom, len)) {
-   if (!data->mark_query)
-   strbuf_addstr(sb, oid_to_hex(>oid));
-   } else if (is_atom("objecttype", atom, len)) {
-   if (data->mark_query)
-   data->info.typep = >type;
-   else
-   strbuf_addstr(sb, typename(data->type));
-   } else if (is_atom("objectsize", atom, len)) {
-   if (data->mark_query)
-   data->info.sizep = >size;
-   else
-   strbuf_addf(sb, "%lu", data->size);
-   } else if (is_atom("objectsize:disk", atom, len)) {
-   if (data->mark_query)
-   data->info.disk_sizep = >disk_size;
-   else
-   strbuf_addf(sb, "%"PRIuMAX, (uintmax_t)data->disk_size);
-   } else if (is_atom("rest", atom, len)) {
-   if (data->mark_query)
-   data->split_on_whitespace = 1;
-   else if (data->rest)
+static void expand_atom(struct strbuf *sb, const char *atom, int len,
+struct expand_data *data)
+{
+   if (is_atom("objectname", atom, len))
+   strbuf_addstr(sb, oid_to_hex(>oid));
+   else if (is_atom("objecttype", atom, len))
+   strbuf_addstr(sb, typename(data->type));
+   else if (is_atom("objectsize", atom, len))
+   strbuf_addf(sb, "%lu", data->size);
+   else if (is_atom("objectsize:disk", atom, len))
+   strbuf_addf(sb, "%"PRIuMAX, (uintmax_t)data->disk_size);
+   else if (is_atom("rest", atom, len)) {
+   if (data->rest)
strbuf_addstr(sb, data->rest);
-   } else if (is_atom("deltabase", atom, len)) {
-   if (data->mark_query)
-   data->info.delta_base_sha1 = data->delta_base_oid.hash;
-   else
-   strbuf_addstr(sb,
- oid_to_hex(>delta_base_oid));
-   } else
+   } else if (is_atom("deltabase", atom, len))
+   strbuf_addstr(sb, oid_to_hex(>delta_base_oid));
+   else
die("unknown format element: %.*s", len, atom);
 }
 
-static size_t expand_format(struct strbuf *sb, const char *start, void *data)
+static size_t expand_format(struct strbuf *sb, const char *start, void *vdata)
 {
const char *end;
+   struct expand_data *data = vdata;
 
if (*start != '(')
return 0;
@@ -265,7 +267,10 @@ static size_t expand_format(struct strbuf *sb, const char 
*start, void *data)
if (!end)
die("format element '%s' does not end in ')'", start);
 
-   expand_atom(sb, start + 1, end - start - 1, data);
+   if (data->mark_query)
+   expand_atom_into_fields(sb, start + 1, end - start - 1, data);
+   else
+   expand_atom(sb, start + 1, end - start - 1, data);
 
return end - start + 1;
 }

--
https://github.com/git/git/pull/450


[PATCH v2 15/18] ref-filter: add is_cat flag

2018-01-10 Thread Olga Telezhnaya
Add is_cat flag, further it helps to get rid of cat_file_data field
in ref_format.

Signed-off-by: Olga Telezhnaia 
Mentored-by: Christian Couder 
Mentored by: Jeff King 
---
 builtin/cat-file.c | 1 +
 ref-filter.c   | 8 +---
 ref-filter.h   | 1 +
 3 files changed, 7 insertions(+), 3 deletions(-)

diff --git a/builtin/cat-file.c b/builtin/cat-file.c
index e11dbf88e386c..289912ab1f858 100644
--- a/builtin/cat-file.c
+++ b/builtin/cat-file.c
@@ -393,6 +393,7 @@ static int batch_objects(struct batch_options *opt)
 */
memset(, 0, sizeof(data));
opt->format->cat_file_data = 
+   opt->format->is_cat = 1;
verify_ref_format(opt->format);
if (opt->cmdmode)
data.split_on_whitespace = 1;
diff --git a/ref-filter.c b/ref-filter.c
index 93248ce18152f..2c955e90bb4c9 100644
--- a/ref-filter.c
+++ b/ref-filter.c
@@ -101,6 +101,7 @@ static struct used_atom {
 } *used_atom;
 static int used_atom_cnt, need_tagged, need_symref;
 struct expand_data *cat_file_info;
+static int is_cat = 0;
 
 static void color_atom_parser(const struct ref_format *format, struct 
used_atom *atom, const char *color_value)
 {
@@ -493,7 +494,7 @@ static int parse_ref_filter_atom(const struct ref_format 
*format,
need_tagged = 1;
if (!strcmp(valid_atom[i].name, "symref"))
need_symref = 1;
-   if (cat_file_info && !strcmp(valid_atoms[i].name, "rest"))
+   if (is_cat && !strcmp(valid_atoms[i].name, "rest"))
cat_file_info->split_on_whitespace = 1;
return at;
 }
@@ -739,6 +740,7 @@ int verify_ref_format(struct ref_format *format)
const char *cp, *sp;
 
cat_file_info = format->cat_file_data;
+   is_cat = format->is_cat;
format->need_color_reset_at_eol = 0;
for (cp = format->format; *cp && (sp = find_next(cp)); ) {
const char *color, *ep = strchr(sp, ')');
@@ -748,7 +750,7 @@ int verify_ref_format(struct ref_format *format)
return error(_("malformed format string %s"), sp);
/* sp points at "%(" and ep points at the closing ")" */
 
-   if (format->cat_file_data) {
+   if (is_cat) {
at = parse_ref_filter_atom(format, valid_cat_file_atom,
   
ARRAY_SIZE(valid_cat_file_atom), sp + 2, ep);
} else {
@@ -1464,7 +1466,7 @@ int populate_value(struct ref_array_item *ref)
ref->symref = "";
}
 
-   if (cat_file_info) {
+   if (is_cat) {
if (!cat_file_info->skip_object_info &&
sha1_object_info_extended(ref->objectname.hash, 
_file_info->info,
  OBJECT_INFO_LOOKUP_REPLACE) < 0) {
diff --git a/ref-filter.h b/ref-filter.h
index 0c7253913735b..12a938b0aa6a3 100644
--- a/ref-filter.h
+++ b/ref-filter.h
@@ -126,6 +126,7 @@ struct ref_format {
 * hopefully would be reduced later.
 */
struct expand_data *cat_file_data;
+   int is_cat;
 };
 
 #define REF_FORMAT_INIT { NULL, 0, -1 }

--
https://github.com/git/git/pull/450


[PATCH v2 17/18] cat-file: move skip_object_info into ref-filter

2018-01-10 Thread Olga Telezhnaya
Move logic related to skip_object_info into ref-filter,
so that cat-file does not use that field at all.

Signed-off-by: Olga Telezhnaia 
Mentored-by: Christian Couder 
Mentored by: Jeff King 
---
 builtin/cat-file.c | 7 +--
 ref-filter.c   | 5 +
 ref-filter.h   | 1 +
 3 files changed, 7 insertions(+), 6 deletions(-)

diff --git a/builtin/cat-file.c b/builtin/cat-file.c
index 5aac10b9808ff..19cee0d22fabe 100644
--- a/builtin/cat-file.c
+++ b/builtin/cat-file.c
@@ -395,16 +395,11 @@ static int batch_objects(struct batch_options *opt)
opt->format->cat_file_data = 
opt->format->is_cat = 1;
opt->format->split_on_whitespace = _on_whitespace;
+   opt->format->all_objects = opt->all_objects;
verify_ref_format(opt->format);
if (opt->cmdmode)
data.split_on_whitespace = 1;
 
-   if (opt->all_objects) {
-   struct object_info empty = OBJECT_INFO_INIT;
-   if (!memcmp(, , sizeof(empty)))
-   data.skip_object_info = 1;
-   }
-
/*
 * If we are printing out the object, then always fill in the type,
 * since we will want to decide whether or not to stream.
diff --git a/ref-filter.c b/ref-filter.c
index 0fb33198fb450..83bacdd8bdd78 100644
--- a/ref-filter.c
+++ b/ref-filter.c
@@ -764,6 +764,11 @@ int verify_ref_format(struct ref_format *format)
}
if (format->need_color_reset_at_eol && !want_color(format->use_color))
format->need_color_reset_at_eol = 0;
+   if (is_cat && format->all_objects) {
+   struct object_info empty = OBJECT_INFO_INIT;
+   if (!memcmp(_file_info->info, , sizeof(empty)))
+   cat_file_info->skip_object_info = 1;
+   }
return 0;
 }
 
diff --git a/ref-filter.h b/ref-filter.h
index aaf1790e43e62..e588d1f50eef6 100644
--- a/ref-filter.h
+++ b/ref-filter.h
@@ -128,6 +128,7 @@ struct ref_format {
struct expand_data *cat_file_data;
int is_cat;
int *split_on_whitespace;
+   int all_objects;
 };
 
 #define REF_FORMAT_INIT { NULL, 0, -1 }

--
https://github.com/git/git/pull/450


[PATCH 17/20] cat-file: add is_cat flag in ref-filter

2018-01-09 Thread Olga Telezhnaya
Add is_cat flag, further it helps to get rid of cat_file_data field
in ref_format.

Signed-off-by: Olga Telezhnaia 
Mentored-by: Christian Couder 
Mentored by: Jeff King 
---
 builtin/cat-file.c | 1 +
 ref-filter.c   | 8 +---
 ref-filter.h   | 1 +
 3 files changed, 7 insertions(+), 3 deletions(-)

diff --git a/builtin/cat-file.c b/builtin/cat-file.c
index e11dbf88e386c..289912ab1f858 100644
--- a/builtin/cat-file.c
+++ b/builtin/cat-file.c
@@ -393,6 +393,7 @@ static int batch_objects(struct batch_options *opt)
 */
memset(, 0, sizeof(data));
opt->format->cat_file_data = 
+   opt->format->is_cat = 1;
verify_ref_format(opt->format);
if (opt->cmdmode)
data.split_on_whitespace = 1;
diff --git a/ref-filter.c b/ref-filter.c
index 112336edbe871..4259c9b9cd767 100644
--- a/ref-filter.c
+++ b/ref-filter.c
@@ -101,6 +101,7 @@ static struct used_atom {
 } *used_atoms;
 static int used_atom_cnt, need_tagged, need_symref;
 struct expand_data *cat_file_info;
+static int is_cat = 0;
 
 static void color_atom_parser(const struct ref_format *format, struct 
used_atom *atom, const char *color_value)
 {
@@ -493,7 +494,7 @@ static int parse_ref_filter_atom(const struct ref_format 
*format,
need_tagged = 1;
if (!strcmp(valid_atoms[i].name, "symref"))
need_symref = 1;
-   if (cat_file_info && !strcmp(valid_atoms[i].name, "rest"))
+   if (is_cat && !strcmp(valid_atoms[i].name, "rest"))
cat_file_info->split_on_whitespace = 1;
return at;
 }
@@ -739,6 +740,7 @@ int verify_ref_format(struct ref_format *format)
const char *cp, *sp;
 
cat_file_info = format->cat_file_data;
+   is_cat = format->is_cat;
format->need_color_reset_at_eol = 0;
for (cp = format->format; *cp && (sp = find_next(cp)); ) {
const char *color, *ep = strchr(sp, ')');
@@ -748,7 +750,7 @@ int verify_ref_format(struct ref_format *format)
return error(_("malformed format string %s"), sp);
/* sp points at "%(" and ep points at the closing ")" */
 
-   if (format->cat_file_data)
+   if (is_cat)
{
at = parse_ref_filter_atom(format, valid_cat_file_atoms,
   
ARRAY_SIZE(valid_cat_file_atoms), sp + 2, ep);
@@ -1466,7 +1468,7 @@ int populate_value(struct ref_array_item *ref)
ref->symref = "";
}
 
-   if (cat_file_info) {
+   if (is_cat) {
if (!cat_file_info->skip_object_info &&
sha1_object_info_extended(ref->objectname.hash, 
_file_info->info,
  OBJECT_INFO_LOOKUP_REPLACE) < 0) {
diff --git a/ref-filter.h b/ref-filter.h
index 9ecf3ef9a..5ba4724a472f6 100644
--- a/ref-filter.h
+++ b/ref-filter.h
@@ -126,6 +126,7 @@ struct ref_format {
 * hopefully would be reduced later.
 */
struct expand_data *cat_file_data;
+   int is_cat;
 };
 
 #define REF_FORMAT_INIT { NULL, 0, -1 }

--
https://github.com/git/git/pull/450


[PATCH 08/20] cat-file: remove unused code

2018-01-09 Thread Olga Telezhnaya
No further need in mark_query parameter.
All logic related to expand_atom_into_fields is not needed here also,
we are doing that in ref-filter.

Signed-off-by: Olga Telezhnaia 
Mentored-by: Christian Couder 
Mentored by: Jeff King 
---
 builtin/cat-file.c | 25 +
 ref-filter.h   |  6 --
 2 files changed, 1 insertion(+), 30 deletions(-)

diff --git a/builtin/cat-file.c b/builtin/cat-file.c
index 0a3f4a47bf1ae..9055fa3a8b0ae 100644
--- a/builtin/cat-file.c
+++ b/builtin/cat-file.c
@@ -182,25 +182,6 @@ static int is_atom(const char *atom, const char *s, int 
slen)
return alen == slen && !memcmp(atom, s, alen);
 }
 
-static void expand_atom_into_fields(struct strbuf *sb, const char *atom, int 
len,
-   struct expand_data *data)
-{
-   if (is_atom("objectname", atom, len))
-   ; /* do nothing */
-   else if (is_atom("objecttype", atom, len))
-   data->info.typep = >type;
-   else if (is_atom("objectsize", atom, len))
-   data->info.sizep = >size;
-   else if (is_atom("objectsize:disk", atom, len))
-   data->info.disk_sizep = >disk_size;
-   else if (is_atom("rest", atom, len))
-   data->split_on_whitespace = 1;
-   else if (is_atom("deltabase", atom, len))
-   data->info.delta_base_sha1 = data->delta_base_oid.hash;
-   else
-   die("unknown format element: %.*s", len, atom);
-}
-
 static void expand_atom(struct strbuf *sb, const char *atom, int len,
 struct expand_data *data)
 {
@@ -232,11 +213,7 @@ static size_t expand_format(struct strbuf *sb, const char 
*start, void *vdata)
if (!end)
die("format element '%s' does not end in ')'", start);
 
-   if (data->mark_query)
-   expand_atom_into_fields(sb, start + 1, end - start - 1, data);
-   else
-   expand_atom(sb, start + 1, end - start - 1, data);
-
+   expand_atom(sb, start + 1, end - start - 1, data);
return end - start + 1;
 }
 
diff --git a/ref-filter.h b/ref-filter.h
index 97169548939cd..590a60ffe034d 100644
--- a/ref-filter.h
+++ b/ref-filter.h
@@ -80,12 +80,6 @@ struct expand_data {
const char *rest;
struct object_id delta_base_oid;
 
-   /*
-* If mark_query is true, we do not expand anything, but rather
-* just mark the object_info with items we wish to query.
-*/
-   int mark_query;
-
/*
 * Whether to split the input on whitespace before feeding it to
 * get_sha1; this is decided during the mark_query phase based on

--
https://github.com/git/git/pull/450


[PATCH 03/20] cat-file: rename variables in ref-filter

2018-01-09 Thread Olga Telezhnaya
Rename some variables for easier reading.
They point not to values, but to arrays.
Added "s" ending so that it could be obvious.

Signed-off-by: Olga Telezhnaia 
Mentored-by: Christian Couder 
Mentored by: Jeff King 
---
 ref-filter.c | 60 ++--
 1 file changed, 30 insertions(+), 30 deletions(-)

diff --git a/ref-filter.c b/ref-filter.c
index 3f9161707e66b..1426f0c28bce7 100644
--- a/ref-filter.c
+++ b/ref-filter.c
@@ -98,7 +98,7 @@ static struct used_atom {
struct refname_atom refname;
char *head;
} u;
-} *used_atom;
+} *used_atoms;
 static int used_atom_cnt, need_tagged, need_symref;
 
 static void color_atom_parser(const struct ref_format *format, struct 
used_atom *atom, const char *color_value)
@@ -325,11 +325,11 @@ static void head_atom_parser(const struct ref_format 
*format, struct used_atom *
atom->u.head = resolve_refdup("HEAD", RESOLVE_REF_READING, NULL, NULL);
 }
 
-static struct {
+static struct valid_atom {
const char *name;
cmp_type cmp_type;
void (*parser)(const struct ref_format *format, struct used_atom *atom, 
const char *arg);
-} valid_atom[] = {
+} valid_atoms[] = {
{ "refname" , FIELD_STR, refname_atom_parser },
{ "objecttype" },
{ "objectsize", FIELD_ULONG },
@@ -410,38 +410,38 @@ static int parse_ref_filter_atom(const struct ref_format 
*format,
 
/* Do we have the atom already used elsewhere? */
for (i = 0; i < used_atom_cnt; i++) {
-   int len = strlen(used_atom[i].name);
-   if (len == ep - atom && !memcmp(used_atom[i].name, atom, len))
+   int len = strlen(used_atoms[i].name);
+   if (len == ep - atom && !memcmp(used_atoms[i].name, atom, len))
return i;
}
 
/*
 * 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
+* shouldn't be used for checking against the valid_atoms
 * table.
 */
arg = memchr(sp, ':', ep - sp);
atom_len = (arg ? arg : ep) - sp;
 
/* Is the atom a valid one? */
-   for (i = 0; i < ARRAY_SIZE(valid_atom); i++) {
-   int len = strlen(valid_atom[i].name);
-   if (len == atom_len && !memcmp(valid_atom[i].name, sp, len))
+   for (i = 0; i < ARRAY_SIZE(valid_atoms); i++) {
+   int len = strlen(valid_atoms[i].name);
+   if (len == atom_len && !memcmp(valid_atoms[i].name, sp, len))
break;
}
 
-   if (ARRAY_SIZE(valid_atom) <= i)
+   if (ARRAY_SIZE(valid_atoms) <= 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);
-   used_atom[at].name = xmemdupz(atom, ep - atom);
-   used_atom[at].type = valid_atom[i].cmp_type;
+   REALLOC_ARRAY(used_atoms, used_atom_cnt);
+   used_atoms[at].name = xmemdupz(atom, ep - atom);
+   used_atoms[at].type = valid_atoms[i].cmp_type;
if (arg) {
-   arg = used_atom[at].name + (arg - atom) + 1;
+   arg = used_atoms[at].name + (arg - atom) + 1;
if (!*arg) {
/*
 * Treat empty sub-arguments list as NULL (i.e.,
@@ -450,12 +450,12 @@ static int parse_ref_filter_atom(const struct ref_format 
*format,
arg = NULL;
}
}
-   memset(_atom[at].u, 0, sizeof(used_atom[at].u));
-   if (valid_atom[i].parser)
-   valid_atom[i].parser(format, _atom[at], arg);
+   memset(_atoms[at].u, 0, sizeof(used_atoms[at].u));
+   if (valid_atoms[i].parser)
+   valid_atoms[i].parser(format, _atoms[at], arg);
if (*atom == '*')
need_tagged = 1;
-   if (!strcmp(valid_atom[i].name, "symref"))
+   if (!strcmp(valid_atoms[i].name, "symref"))
need_symref = 1;
return at;
 }
@@ -711,7 +711,7 @@ int verify_ref_format(struct ref_format *format)
at = parse_ref_filter_atom(format, sp + 2, ep);
cp = ep + 1;
 
-   if (skip_prefix(used_atom[at].name, "color:", ))
+   if (skip_prefix(used_atoms[at].name, "color:", ))
format->need_color_reset_at_eol = !!strcmp(color, 
"reset");
}
if (format->need_color_reset_at_eol && !want_color(format->use_color))
@@ -762,7 +762,7 @@ static void grab_common_values(struct atom_value *val, int 
deref, struct object
int i;
 
for (i = 0; i < used_atom_cnt; i++) {
-   const char *name = used_atom[i].name;

[PATCH 20/20] cat-file: make cat_file_info variable independent

2018-01-09 Thread Olga Telezhnaya
Remove connection between expand_data variable
in cat-file and in ref-filter.
It will help further to get rid of using expand_data in cat-file.

Signed-off-by: Olga Telezhnaia 
Mentored-by: Christian Couder 
Mentored by: Jeff King 
---
 builtin/cat-file.c |  2 +-
 ref-filter.c   | 28 ++--
 ref-filter.h   |  1 -
 3 files changed, 15 insertions(+), 16 deletions(-)

diff --git a/builtin/cat-file.c b/builtin/cat-file.c
index 19cee0d22fabe..ffa8e61213e36 100644
--- a/builtin/cat-file.c
+++ b/builtin/cat-file.c
@@ -289,6 +289,7 @@ static void batch_object_write(const char *obj_name, struct 
batch_options *opt,
item.start_of_request = obj_name;
 
if (populate_value()) return;
+   data->type = item.type;
 
strbuf_expand(, opt->format->format, expand_format, );
strbuf_addch(, '\n');
@@ -392,7 +393,6 @@ static int batch_objects(struct batch_options *opt)
 * object.
 */
memset(, 0, sizeof(data));
-   opt->format->cat_file_data = 
opt->format->is_cat = 1;
opt->format->split_on_whitespace = _on_whitespace;
opt->format->all_objects = opt->all_objects;
diff --git a/ref-filter.c b/ref-filter.c
index dbca6856432c0..a8a93b488db37 100644
--- a/ref-filter.c
+++ b/ref-filter.c
@@ -100,7 +100,7 @@ static struct used_atom {
} u;
 } *used_atoms;
 static int used_atom_cnt, need_tagged, need_symref;
-struct expand_data *cat_file_info;
+struct expand_data cat_file_info;
 static int is_cat = 0;
 
 static void color_atom_parser(const struct ref_format *format, struct 
used_atom *atom, const char *color_value)
@@ -256,9 +256,9 @@ static void objectname_atom_parser(const struct ref_format 
*format, struct used_
 static void objectsize_atom_parser(const struct ref_format *format, struct 
used_atom *atom, const char *arg)
 {
if (!arg)
-   cat_file_info->info.sizep = _file_info->size;
+   cat_file_info.info.sizep = _file_info.size;
else if (!strcmp(arg, "disk"))
-   cat_file_info->info.disk_sizep = _file_info->disk_size;
+   cat_file_info.info.disk_sizep = _file_info.disk_size;
else
die(_("urecognized %%(objectsize) argument: %s"), arg);
 }
@@ -266,7 +266,7 @@ static void objectsize_atom_parser(const struct ref_format 
*format, struct used_
 static void objecttype_atom_parser(const struct ref_format *format, struct 
used_atom *atom, const char *arg)
 {
if (!arg)
-   cat_file_info->info.typep = _file_info->type;
+   cat_file_info.info.typep = _file_info.type;
else
die(_("urecognized %%(objecttype) argument: %s"), arg);
 }
@@ -274,7 +274,7 @@ static void objecttype_atom_parser(const struct ref_format 
*format, struct used_
 static void deltabase_atom_parser(const struct ref_format *format, struct 
used_atom *atom, const char *arg)
 {
if (!arg)
-   cat_file_info->info.delta_base_sha1 = 
cat_file_info->delta_base_oid.hash;
+   cat_file_info.info.delta_base_sha1 = 
cat_file_info.delta_base_oid.hash;
else
die(_("urecognized %%(deltabase) argument: %s"), arg);
 }
@@ -739,7 +739,6 @@ int verify_ref_format(struct ref_format *format)
 {
const char *cp, *sp;
 
-   cat_file_info = format->cat_file_data;
is_cat = format->is_cat;
format->need_color_reset_at_eol = 0;
for (cp = format->format; *cp && (sp = find_next(cp)); ) {
@@ -768,8 +767,8 @@ int verify_ref_format(struct ref_format *format)
format->need_color_reset_at_eol = 0;
if (is_cat && format->all_objects) {
struct object_info empty = OBJECT_INFO_INIT;
-   if (!memcmp(_file_info->info, , sizeof(empty)))
-   cat_file_info->skip_object_info = 1;
+   if (!memcmp(_file_info.info, , sizeof(empty)))
+   cat_file_info.skip_object_info = 1;
}
return 0;
 }
@@ -1474,18 +1473,19 @@ int populate_value(struct ref_array_item *ref)
}
 
if (is_cat) {
-   if (!cat_file_info->skip_object_info &&
-   sha1_object_info_extended(ref->objectname.hash, 
_file_info->info,
+   if (!cat_file_info.info.typep) cat_file_info.info.typep = 
_file_info.type;
+   if (!cat_file_info.skip_object_info &&
+   sha1_object_info_extended(ref->objectname.hash, 
_file_info.info,
  OBJECT_INFO_LOOKUP_REPLACE) < 0) {
const char *e = ref->start_of_request;
printf("%s missing\n", e ? e : 
oid_to_hex(>objectname));
fflush(stdout);
return -1;
}
-   ref->type = cat_file_info->type;
-   ref->size = cat_file_info->size;
-   

[PATCH 13/20] cat-file: start use ref_array_item struct

2018-01-09 Thread Olga Telezhnaya
Moving from using expand_data to ref_array_item structure.
That helps us to reuse functions from ref-filter easier.

Signed-off-by: Olga Telezhnaia 
Mentored-by: Christian Couder 
Mentored by: Jeff King 
---
 builtin/cat-file.c | 30 +++---
 ref-filter.h   |  5 +
 2 files changed, 24 insertions(+), 11 deletions(-)

diff --git a/builtin/cat-file.c b/builtin/cat-file.c
index 1f331559e55c7..1c92194faaede 100644
--- a/builtin/cat-file.c
+++ b/builtin/cat-file.c
@@ -183,26 +183,26 @@ static int is_atom(const char *atom, const char *s, int 
slen)
 }
 
 static void expand_atom(struct strbuf *sb, const char *atom, int len,
-struct expand_data *data)
+struct ref_array_item *item)
 {
if (is_atom("objectname", atom, len))
-   strbuf_addstr(sb, oid_to_hex(>oid));
+   strbuf_addstr(sb, oid_to_hex(>objectname));
else if (is_atom("objecttype", atom, len))
-   strbuf_addstr(sb, typename(data->type));
+   strbuf_addstr(sb, typename(item->type));
else if (is_atom("objectsize", atom, len))
-   strbuf_addf(sb, "%lu", data->size);
+   strbuf_addf(sb, "%lu", item->size);
else if (is_atom("objectsize:disk", atom, len))
-   strbuf_addf(sb, "%"PRIuMAX, (uintmax_t)data->disk_size);
+   strbuf_addf(sb, "%"PRIuMAX, (uintmax_t)item->disk_size);
else if (is_atom("rest", atom, len))
-   strbuf_addstr(sb, data->rest);
+   strbuf_addstr(sb, item->rest);
else if (is_atom("deltabase", atom, len))
-   strbuf_addstr(sb, oid_to_hex(>delta_base_oid));
+   strbuf_addstr(sb, oid_to_hex(>delta_base_oid));
 }
 
-static size_t expand_format(struct strbuf *sb, const char *start, void *vdata)
+static size_t expand_format(struct strbuf *sb, const char *start, void *data)
 {
const char *end;
-   struct expand_data *data = vdata;
+   struct ref_array_item *item = data;
 
if (*start != '(')
return 0;
@@ -210,7 +210,7 @@ static size_t expand_format(struct strbuf *sb, const char 
*start, void *vdata)
if (!end)
die("format element '%s' does not end in ')'", start);
 
-   expand_atom(sb, start + 1, end - start - 1, data);
+   expand_atom(sb, start + 1, end - start - 1, item);
return end - start + 1;
 }
 
@@ -282,6 +282,7 @@ static void batch_object_write(const char *obj_name, struct 
batch_options *opt,
   struct expand_data *data)
 {
struct strbuf buf = STRBUF_INIT;
+   struct ref_array_item item;
 
if (!data->skip_object_info &&
sha1_object_info_extended(data->oid.hash, >info,
@@ -292,7 +293,14 @@ static void batch_object_write(const char *obj_name, 
struct batch_options *opt,
return;
}
 
-   strbuf_expand(, opt->format->format, expand_format, data);
+   item.objectname = data->oid;
+   item.type = data->type;
+   item.size = data->size;
+   item.disk_size = data->disk_size;
+   item.rest = data->rest;
+   item.delta_base_oid = data->delta_base_oid;
+
+   strbuf_expand(, opt->format->format, expand_format, );
strbuf_addch(, '\n');
batch_write(opt, buf.buf, buf.len);
strbuf_release();
diff --git a/ref-filter.h b/ref-filter.h
index de3fd3263ac64..28774e8e0f771 100644
--- a/ref-filter.h
+++ b/ref-filter.h
@@ -40,6 +40,11 @@ struct ref_array_item {
const char *symref;
struct commit *commit;
struct atom_value *values;
+   enum object_type type;
+   unsigned long size;
+   off_t disk_size;
+   const char *rest;
+   struct object_id delta_base_oid;
char refname[FLEX_ARRAY];
 };
 

--
https://github.com/git/git/pull/450


[PATCH 16/20] cat-file: get rid of expand_atom_into_fields

2018-01-09 Thread Olga Telezhnaya
Remove expand_atom_into_fields function and create same logic
in terms of ref-filter style.

Signed-off-by: Olga Telezhnaia 
Mentored-by: Christian Couder 
Mentored by: Jeff King 
---
 ref-filter.c | 45 +
 1 file changed, 21 insertions(+), 24 deletions(-)

diff --git a/ref-filter.c b/ref-filter.c
index 7df6d7e3d6511..112336edbe871 100644
--- a/ref-filter.c
+++ b/ref-filter.c
@@ -255,13 +255,29 @@ static void objectname_atom_parser(const struct 
ref_format *format, struct used_
 static void objectsize_atom_parser(const struct ref_format *format, struct 
used_atom *atom, const char *arg)
 {
if (!arg)
-   ; /* default to normal object size */
+   cat_file_info->info.sizep = _file_info->size;
else if (!strcmp(arg, "disk"))
cat_file_info->info.disk_sizep = _file_info->disk_size;
else
die(_("urecognized %%(objectsize) argument: %s"), arg);
 }
 
+static void objecttype_atom_parser(const struct ref_format *format, struct 
used_atom *atom, const char *arg)
+{
+   if (!arg)
+   cat_file_info->info.typep = _file_info->type;
+   else
+   die(_("urecognized %%(objecttype) argument: %s"), arg);
+}
+
+static void deltabase_atom_parser(const struct ref_format *format, struct 
used_atom *atom, const char *arg)
+{
+   if (!arg)
+   cat_file_info->info.delta_base_sha1 = 
cat_file_info->delta_base_oid.hash;
+   else
+   die(_("urecognized %%(deltabase) argument: %s"), arg);
+}
+
 static void refname_atom_parser(const struct ref_format *format, struct 
used_atom *atom, const char *arg)
 {
refname_atom_parser_internal(>u.refname, arg, atom->name);
@@ -384,10 +400,10 @@ static struct valid_atom {
 
 static struct valid_atom valid_cat_file_atoms[] = {
{ "objectname" },
-   { "objecttype" },
+   { "objecttype", FIELD_STR, objecttype_atom_parser },
{ "objectsize", FIELD_ULONG, objectsize_atom_parser },
{ "rest" },
-   { "deltabase" },
+   { "deltabase", FIELD_STR, deltabase_atom_parser },
 };
 
 #define REF_FORMATTING_STATE_INIT  { 0, NULL }
@@ -411,25 +427,6 @@ struct atom_value {
struct used_atom *atom;
 };
 
-static int is_atom(const char *atom, const char *s, int slen)
-{
-   int alen = strlen(atom);
-   return alen == slen && !memcmp(atom, s, alen);
-}
-
-static void expand_atom_into_fields(const char *atom, int len,
-   struct expand_data *data)
-{
-   if (is_atom("objecttype", atom, len))
-   data->info.typep = >type;
-   else if (is_atom("objectsize", atom, len))
-   data->info.sizep = >size;
-   else if (is_atom("rest", atom, len))
-   data->split_on_whitespace = 1;
-   else if (is_atom("deltabase", atom, len))
-   data->info.delta_base_sha1 = data->delta_base_oid.hash;
-}
-
 /*
  * Used to parse format string and sort specifiers
  */
@@ -496,8 +493,8 @@ static int parse_ref_filter_atom(const struct ref_format 
*format,
need_tagged = 1;
if (!strcmp(valid_atoms[i].name, "symref"))
need_symref = 1;
-   if (cat_file_info)
-   expand_atom_into_fields(atom, atom_len, cat_file_info);
+   if (cat_file_info && !strcmp(valid_atoms[i].name, "rest"))
+   cat_file_info->split_on_whitespace = 1;
return at;
 }
 

--
https://github.com/git/git/pull/450


[PATCH 01/20] cat-file: split expand_atom into 2 functions

2018-01-09 Thread Olga Telezhnaya
Split expand_atom function into 2 different functions,
expand_atom_into_fields prepares variable for further filling,
(new) expand_atom creates resulting string.
Need that for further reusing of formatting logic from ref-filter.

Signed-off-by: Olga Telezhnaia 
Mentored-by: Christian Couder 
Mentored by: Jeff King 
---
 builtin/cat-file.c | 73 +-
 1 file changed, 39 insertions(+), 34 deletions(-)

diff --git a/builtin/cat-file.c b/builtin/cat-file.c
index f5fa4fd75af26..f783b39b9bd5c 100644
--- a/builtin/cat-file.c
+++ b/builtin/cat-file.c
@@ -217,47 +217,49 @@ static int is_atom(const char *atom, const char *s, int 
slen)
return alen == slen && !memcmp(atom, s, alen);
 }
 
-static void expand_atom(struct strbuf *sb, const char *atom, int len,
-   void *vdata)
+static void expand_atom_into_fields(struct strbuf *sb, const char *atom, int 
len,
+   struct expand_data *data)
 {
-   struct expand_data *data = vdata;
+   if (is_atom("objectname", atom, len))
+   ; /* do nothing */
+   else if (is_atom("objecttype", atom, len))
+   data->info.typep = >type;
+   else if (is_atom("objectsize", atom, len))
+   data->info.sizep = >size;
+   else if (is_atom("objectsize:disk", atom, len))
+   data->info.disk_sizep = >disk_size;
+   else if (is_atom("rest", atom, len))
+   data->split_on_whitespace = 1;
+   else if (is_atom("deltabase", atom, len))
+   data->info.delta_base_sha1 = data->delta_base_oid.hash;
+   else
+   die("unknown format element: %.*s", len, atom);
+}
 
-   if (is_atom("objectname", atom, len)) {
-   if (!data->mark_query)
-   strbuf_addstr(sb, oid_to_hex(>oid));
-   } else if (is_atom("objecttype", atom, len)) {
-   if (data->mark_query)
-   data->info.typep = >type;
-   else
-   strbuf_addstr(sb, typename(data->type));
-   } else if (is_atom("objectsize", atom, len)) {
-   if (data->mark_query)
-   data->info.sizep = >size;
-   else
-   strbuf_addf(sb, "%lu", data->size);
-   } else if (is_atom("objectsize:disk", atom, len)) {
-   if (data->mark_query)
-   data->info.disk_sizep = >disk_size;
-   else
-   strbuf_addf(sb, "%"PRIuMAX, (uintmax_t)data->disk_size);
-   } else if (is_atom("rest", atom, len)) {
-   if (data->mark_query)
-   data->split_on_whitespace = 1;
-   else if (data->rest)
+static void expand_atom(struct strbuf *sb, const char *atom, int len,
+struct expand_data *data)
+{
+   if (is_atom("objectname", atom, len))
+   strbuf_addstr(sb, oid_to_hex(>oid));
+   else if (is_atom("objecttype", atom, len))
+   strbuf_addstr(sb, typename(data->type));
+   else if (is_atom("objectsize", atom, len))
+   strbuf_addf(sb, "%lu", data->size);
+   else if (is_atom("objectsize:disk", atom, len))
+   strbuf_addf(sb, "%"PRIuMAX, (uintmax_t)data->disk_size);
+   else if (is_atom("rest", atom, len)) {
+   if (data->rest)
strbuf_addstr(sb, data->rest);
-   } else if (is_atom("deltabase", atom, len)) {
-   if (data->mark_query)
-   data->info.delta_base_sha1 = data->delta_base_oid.hash;
-   else
-   strbuf_addstr(sb,
- oid_to_hex(>delta_base_oid));
-   } else
+   } else if (is_atom("deltabase", atom, len))
+   strbuf_addstr(sb, oid_to_hex(>delta_base_oid));
+   else
die("unknown format element: %.*s", len, atom);
 }
 
-static size_t expand_format(struct strbuf *sb, const char *start, void *data)
+static size_t expand_format(struct strbuf *sb, const char *start, void *vdata)
 {
const char *end;
+   struct expand_data *data = vdata;
 
if (*start != '(')
return 0;
@@ -265,7 +267,10 @@ static size_t expand_format(struct strbuf *sb, const char 
*start, void *data)
if (!end)
die("format element '%s' does not end in ')'", start);
 
-   expand_atom(sb, start + 1, end - start - 1, data);
+   if (data->mark_query)
+   expand_atom_into_fields(sb, start + 1, end - start - 1, data);
+   else
+   expand_atom(sb, start + 1, end - start - 1, data);
 
return end - start + 1;
 }

--
https://github.com/git/git/pull/450


[PATCH 18/20] cat-file: add split_on_whitespace flag

2018-01-09 Thread Olga Telezhnaya
Add flag to ref_format struct so that we could pass needed info
to cat-file.

Signed-off-by: Olga Telezhnaia 
Mentored-by: Christian Couder 
Mentored by: Jeff King 
---
 builtin/cat-file.c | 1 +
 ref-filter.c   | 4 ++--
 ref-filter.h   | 1 +
 3 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/builtin/cat-file.c b/builtin/cat-file.c
index 289912ab1f858..5aac10b9808ff 100644
--- a/builtin/cat-file.c
+++ b/builtin/cat-file.c
@@ -394,6 +394,7 @@ static int batch_objects(struct batch_options *opt)
memset(, 0, sizeof(data));
opt->format->cat_file_data = 
opt->format->is_cat = 1;
+   opt->format->split_on_whitespace = _on_whitespace;
verify_ref_format(opt->format);
if (opt->cmdmode)
data.split_on_whitespace = 1;
diff --git a/ref-filter.c b/ref-filter.c
index 4259c9b9cd767..ee27edb2dad56 100644
--- a/ref-filter.c
+++ b/ref-filter.c
@@ -494,8 +494,8 @@ static int parse_ref_filter_atom(const struct ref_format 
*format,
need_tagged = 1;
if (!strcmp(valid_atoms[i].name, "symref"))
need_symref = 1;
-   if (is_cat && !strcmp(valid_atoms[i].name, "rest"))
-   cat_file_info->split_on_whitespace = 1;
+   if (!strcmp(valid_atoms[i].name, "rest"))
+   *format->split_on_whitespace = 1;
return at;
 }
 
diff --git a/ref-filter.h b/ref-filter.h
index 5ba4724a472f6..3228661414623 100644
--- a/ref-filter.h
+++ b/ref-filter.h
@@ -127,6 +127,7 @@ struct ref_format {
 */
struct expand_data *cat_file_data;
int is_cat;
+   int *split_on_whitespace;
 };
 
 #define REF_FORMAT_INIT { NULL, 0, -1 }

--
https://github.com/git/git/pull/450


[PATCH 12/20] cat-file: rename variable in ref-filter

2018-01-09 Thread Olga Telezhnaya
Rename variable for easier reading.
It points not to values, but to arrays.
Added "s" ending so that it could be obvious.

Signed-off-by: Olga Telezhnaia 
Mentored-by: Christian Couder 
Mentored by: Jeff King 
---
 ref-filter.c | 16 
 ref-filter.h |  2 +-
 2 files changed, 9 insertions(+), 9 deletions(-)

diff --git a/ref-filter.c b/ref-filter.c
index 1b8c8787190a9..56d2687e07df9 100644
--- a/ref-filter.c
+++ b/ref-filter.c
@@ -1418,7 +1418,7 @@ static void need_object(struct ref_array_item *ref) {
die(_("parse_object_buffer failed on %s for %s"),
oid_to_hex(>objectname), ref->refname);
 
-   grab_values(ref->value, 0, obj, buf, size);
+   grab_values(ref->values, 0, obj, buf, size);
if (!eaten)
free(buf);
 
@@ -1448,7 +1448,7 @@ static void need_object(struct ref_array_item *ref) {
if (!obj)
die(_("parse_object_buffer failed on %s for %s"),
oid_to_hex(tagged), ref->refname);
-   grab_values(ref->value, 1, obj, buf, size);
+   grab_values(ref->values, 1, obj, buf, size);
if (!eaten)
free(buf);
 }
@@ -1460,7 +1460,7 @@ static void populate_value(struct ref_array_item *ref)
 {
int i;
 
-   ref->value = xcalloc(used_atom_cnt, sizeof(struct atom_value));
+   ref->values = xcalloc(used_atom_cnt, sizeof(struct atom_value));
 
if (need_symref && (ref->flag & REF_ISSYMREF) && !ref->symref) {
ref->symref = resolve_refdup(ref->refname, RESOLVE_REF_READING,
@@ -1473,7 +1473,7 @@ static void populate_value(struct ref_array_item *ref)
for (i = 0; i < used_atom_cnt; i++) {
struct used_atom *atom = _atoms[i];
const char *name = used_atoms[i].name;
-   struct atom_value *v = >value[i];
+   struct atom_value *v = >values[i];
int deref = 0;
const char *refname;
struct branch *branch = NULL;
@@ -1571,7 +1571,7 @@ static void populate_value(struct ref_array_item *ref)
}
 
for (i = 0; i < used_atom_cnt; i++) {
-   struct atom_value *v = >value[i];
+   struct atom_value *v = >values[i];
if (v->s == NULL) {
need_object(ref);
break;
@@ -1586,11 +1586,11 @@ static void populate_value(struct ref_array_item *ref)
  */
 static void get_ref_atom_value(struct ref_array_item *ref, int atom, struct 
atom_value **v)
 {
-   if (!ref->value) {
+   if (!ref->values) {
populate_value(ref);
-   fill_missing_values(ref->value);
+   fill_missing_values(ref->values);
}
-   *v = >value[atom];
+   *v = >values[atom];
 }
 
 /*
diff --git a/ref-filter.h b/ref-filter.h
index 590a60ffe034d..de3fd3263ac64 100644
--- a/ref-filter.h
+++ b/ref-filter.h
@@ -39,7 +39,7 @@ struct ref_array_item {
unsigned int kind;
const char *symref;
struct commit *commit;
-   struct atom_value *value;
+   struct atom_value *values;
char refname[FLEX_ARRAY];
 };
 

--
https://github.com/git/git/pull/450


[PATCH 02/20] cat-file: reuse struct ref_format

2018-01-09 Thread Olga Telezhnaya
Start using ref_format struct instead of simple char*.
Need that for further reusing of formatting logic from ref-filter.

Signed-off-by: Olga Telezhnaia 
Mentored-by: Christian Couder 
Mentored by: Jeff King 
---
 builtin/cat-file.c | 16 +---
 1 file changed, 9 insertions(+), 7 deletions(-)

diff --git a/builtin/cat-file.c b/builtin/cat-file.c
index f783b39b9bd5c..7655a9a726773 100644
--- a/builtin/cat-file.c
+++ b/builtin/cat-file.c
@@ -13,15 +13,16 @@
 #include "tree-walk.h"
 #include "sha1-array.h"
 #include "packfile.h"
+#include "ref-filter.h"
 
 struct batch_options {
+   struct ref_format *format;
int enabled;
int follow_symlinks;
int print_contents;
int buffer_output;
int all_objects;
int cmdmode; /* may be 'w' or 'c' for --filters or --textconv */
-   const char *format;
 };
 
 static const char *force_path;
@@ -353,7 +354,7 @@ static void batch_object_write(const char *obj_name, struct 
batch_options *opt,
return;
}
 
-   strbuf_expand(, opt->format, expand_format, data);
+   strbuf_expand(, opt->format->format, expand_format, data);
strbuf_addch(, '\n');
batch_write(opt, buf.buf, buf.len);
strbuf_release();
@@ -446,8 +447,8 @@ static int batch_objects(struct batch_options *opt)
int save_warning;
int retval = 0;
 
-   if (!opt->format)
-   opt->format = "%(objectname) %(objecttype) %(objectsize)";
+   if (!opt->format->format)
+   opt->format->format = "%(objectname) %(objecttype) 
%(objectsize)";
 
/*
 * Expand once with our special mark_query flag, which will prime the
@@ -456,7 +457,7 @@ static int batch_objects(struct batch_options *opt)
 */
memset(, 0, sizeof(data));
data.mark_query = 1;
-   strbuf_expand(, opt->format, expand_format, );
+   strbuf_expand(, opt->format->format, expand_format, );
data.mark_query = 0;
if (opt->cmdmode)
data.split_on_whitespace = 1;
@@ -548,7 +549,7 @@ static int batch_option_callback(const struct option *opt,
 
bo->enabled = 1;
bo->print_contents = !strcmp(opt->long_name, "batch");
-   bo->format = arg;
+   bo->format->format = arg;
 
return 0;
 }
@@ -557,7 +558,8 @@ int cmd_cat_file(int argc, const char **argv, const char 
*prefix)
 {
int opt = 0;
const char *exp_type = NULL, *obj_name = NULL;
-   struct batch_options batch = {0};
+   struct ref_format format = REF_FORMAT_INIT;
+   struct batch_options batch = {};
int unknown_type = 0;
 
const struct option options[] = {

--
https://github.com/git/git/pull/450


[PATCH 06/20] cat-file: start migrating to ref-filter

2018-01-09 Thread Olga Telezhnaya
Start moving all formatting stuff from cat-file to ref-filter.
Start from simple moving, it would be integrated into
all ref-filter processes further.

Signed-off-by: Olga Telezhnaia 
Mentored-by: Christian Couder 
Mentored by: Jeff King 
---
 builtin/cat-file.c |  5 ++---
 ref-filter.c   | 42 +-
 ref-filter.h   |  6 ++
 3 files changed, 45 insertions(+), 8 deletions(-)

diff --git a/builtin/cat-file.c b/builtin/cat-file.c
index 7fd5b960ad698..0a3f4a47bf1ae 100644
--- a/builtin/cat-file.c
+++ b/builtin/cat-file.c
@@ -420,9 +420,8 @@ static int batch_objects(struct batch_options *opt)
 * object.
 */
memset(, 0, sizeof(data));
-   data.mark_query = 1;
-   strbuf_expand(, opt->format->format, expand_format, );
-   data.mark_query = 0;
+   opt->format->cat_file_data = 
+   verify_ref_format(opt->format);
if (opt->cmdmode)
data.split_on_whitespace = 1;
 
diff --git a/ref-filter.c b/ref-filter.c
index 2d6e81fe1ab00..98bb10185ae96 100644
--- a/ref-filter.c
+++ b/ref-filter.c
@@ -693,6 +693,31 @@ static const char *find_next(const char *cp)
return NULL;
 }
 
+static int is_atom(const char *atom, const char *s, int slen)
+{
+   int alen = strlen(atom);
+   return alen == slen && !memcmp(atom, s, alen);
+}
+
+static void expand_atom_into_fields(const char *atom, int len,
+   struct expand_data *data)
+{
+   if (is_atom("objectname", atom, len))
+   ; /* do nothing */
+   else if (is_atom("objecttype", atom, len))
+   data->info.typep = >type;
+   else if (is_atom("objectsize", atom, len))
+   data->info.sizep = >size;
+   else if (is_atom("objectsize:disk", atom, len))
+   data->info.disk_sizep = >disk_size;
+   else if (is_atom("rest", atom, len))
+   data->split_on_whitespace = 1;
+   else if (is_atom("deltabase", atom, len))
+   data->info.delta_base_sha1 = data->delta_base_oid.hash;
+   else
+   die("unknown format element: %.*s", len, atom);
+}
+
 /*
  * Make sure the format string is well formed, and parse out
  * the used atoms.
@@ -709,12 +734,19 @@ int verify_ref_format(struct ref_format *format)
if (!ep)
return error(_("malformed format string %s"), sp);
/* sp points at "%(" and ep points at the closing ")" */
-   at = parse_ref_filter_atom(format, valid_atoms,
-  ARRAY_SIZE(valid_atoms), sp + 2, ep);
-   cp = ep + 1;
 
-   if (skip_prefix(used_atoms[at].name, "color:", ))
-   format->need_color_reset_at_eol = !!strcmp(color, 
"reset");
+   if (format->cat_file_data)
+   expand_atom_into_fields(sp + 2, ep - sp - 2,
+   format->cat_file_data);
+   else
+   {
+   at = parse_ref_filter_atom(format, valid_atoms,
+  ARRAY_SIZE(valid_atoms), sp 
+ 2, ep);
+   if (skip_prefix(used_atoms[at].name, "color:", ))
+   format->need_color_reset_at_eol = 
!!strcmp(color, "reset");
+   }
+
+   cp = ep + 1;
}
if (format->need_color_reset_at_eol && !want_color(format->use_color))
format->need_color_reset_at_eol = 0;
diff --git a/ref-filter.h b/ref-filter.h
index 16d00e4b1bded..97169548939cd 100644
--- a/ref-filter.h
+++ b/ref-filter.h
@@ -119,6 +119,12 @@ struct ref_format {
 
/* Internal state to ref-filter */
int need_color_reset_at_eol;
+
+   /*
+* Helps to move all formatting logic from cat-file to ref-filter,
+* hopefully would be reduced later.
+*/
+   struct expand_data *cat_file_data;
 };
 
 #define REF_FORMAT_INIT { NULL, 0, -1 }

--
https://github.com/git/git/pull/450


[PATCH 07/20] cat-file: reuse parse_ref_filter_atom

2018-01-09 Thread Olga Telezhnaya
Continue migrating formatting logic from cat-file to ref-filter.
Reuse parse_ref_filter_atom for unifying all processes in ref-filter
and further reducing of expand_atom_into_fields function.

Signed-off-by: Olga Telezhnaia 
Mentored-by: Christian Couder 
Mentored by: Jeff King 
---
 ref-filter.c | 73 +---
 1 file changed, 45 insertions(+), 28 deletions(-)

diff --git a/ref-filter.c b/ref-filter.c
index 98bb10185ae96..2bd9a8fc4e39c 100644
--- a/ref-filter.c
+++ b/ref-filter.c
@@ -100,6 +100,7 @@ static struct used_atom {
} u;
 } *used_atoms;
 static int used_atom_cnt, need_tagged, need_symref;
+struct expand_data *cat_file_info;
 
 static void color_atom_parser(const struct ref_format *format, struct 
used_atom *atom, const char *color_value)
 {
@@ -251,6 +252,16 @@ static void objectname_atom_parser(const struct ref_format 
*format, struct used_
die(_("unrecognized %%(objectname) argument: %s"), arg);
 }
 
+static void objectsize_atom_parser(const struct ref_format *format, struct 
used_atom *atom, const char *arg)
+{
+   if (!arg)
+   ; /* default to normal object size */
+   else if (!strcmp(arg, "disk"))
+   cat_file_info->info.disk_sizep = _file_info->disk_size;
+   else
+   die(_("urecognized %%(objectsize) argument: %s"), arg);
+}
+
 static void refname_atom_parser(const struct ref_format *format, struct 
used_atom *atom, const char *arg)
 {
refname_atom_parser_internal(>u.refname, arg, atom->name);
@@ -371,6 +382,14 @@ static struct valid_atom {
{ "else" },
 };
 
+static struct valid_atom valid_cat_file_atoms[] = {
+   { "objectname" },
+   { "objecttype" },
+   { "objectsize", FIELD_ULONG, objectsize_atom_parser },
+   { "rest" },
+   { "deltabase" },
+};
+
 #define REF_FORMATTING_STATE_INIT  { 0, NULL }
 
 struct ref_formatting_stack {
@@ -392,6 +411,25 @@ struct atom_value {
struct used_atom *atom;
 };
 
+static int is_atom(const char *atom, const char *s, int slen)
+{
+   int alen = strlen(atom);
+   return alen == slen && !memcmp(atom, s, alen);
+}
+
+static void expand_atom_into_fields(const char *atom, int len,
+   struct expand_data *data)
+{
+   if (is_atom("objecttype", atom, len))
+   data->info.typep = >type;
+   else if (is_atom("objectsize", atom, len))
+   data->info.sizep = >size;
+   else if (is_atom("rest", atom, len))
+   data->split_on_whitespace = 1;
+   else if (is_atom("deltabase", atom, len))
+   data->info.delta_base_sha1 = data->delta_base_oid.hash;
+}
+
 /*
  * Used to parse format string and sort specifiers
  */
@@ -458,6 +496,8 @@ static int parse_ref_filter_atom(const struct ref_format 
*format,
need_tagged = 1;
if (!strcmp(valid_atoms[i].name, "symref"))
need_symref = 1;
+   if (cat_file_info)
+   expand_atom_into_fields(atom, atom_len, cat_file_info);
return at;
 }
 
@@ -693,31 +733,6 @@ static const char *find_next(const char *cp)
return NULL;
 }
 
-static int is_atom(const char *atom, const char *s, int slen)
-{
-   int alen = strlen(atom);
-   return alen == slen && !memcmp(atom, s, alen);
-}
-
-static void expand_atom_into_fields(const char *atom, int len,
-   struct expand_data *data)
-{
-   if (is_atom("objectname", atom, len))
-   ; /* do nothing */
-   else if (is_atom("objecttype", atom, len))
-   data->info.typep = >type;
-   else if (is_atom("objectsize", atom, len))
-   data->info.sizep = >size;
-   else if (is_atom("objectsize:disk", atom, len))
-   data->info.disk_sizep = >disk_size;
-   else if (is_atom("rest", atom, len))
-   data->split_on_whitespace = 1;
-   else if (is_atom("deltabase", atom, len))
-   data->info.delta_base_sha1 = data->delta_base_oid.hash;
-   else
-   die("unknown format element: %.*s", len, atom);
-}
-
 /*
  * Make sure the format string is well formed, and parse out
  * the used atoms.
@@ -726,6 +741,7 @@ int verify_ref_format(struct ref_format *format)
 {
const char *cp, *sp;
 
+   cat_file_info = format->cat_file_data;
format->need_color_reset_at_eol = 0;
for (cp = format->format; *cp && (sp = find_next(cp)); ) {
const char *color, *ep = strchr(sp, ')');
@@ -736,9 +752,10 @@ int verify_ref_format(struct ref_format *format)
/* sp points at "%(" and ep points at the closing ")" */
 
if (format->cat_file_data)
-   expand_atom_into_fields(sp + 2, ep - sp - 2,
-   format->cat_file_data);
-   else
+   {
+

[PATCH 05/20] cat-file: move struct expand_data into ref-filter

2018-01-09 Thread Olga Telezhnaya
Need that for further reusing of formatting logic in cat-file.
Have plans to get rid of using expand_data in cat-file at all,
and use it only in ref-filter for collecting, formatting and printing
needed data.

Signed-off-by: Olga Telezhnaia 
Mentored-by: Christian Couder 
Mentored by: Jeff King 
---
 builtin/cat-file.c | 36 
 ref-filter.h   | 36 
 2 files changed, 36 insertions(+), 36 deletions(-)

diff --git a/builtin/cat-file.c b/builtin/cat-file.c
index 7655a9a726773..7fd5b960ad698 100644
--- a/builtin/cat-file.c
+++ b/builtin/cat-file.c
@@ -176,42 +176,6 @@ static int cat_one_file(int opt, const char *exp_type, 
const char *obj_name,
return 0;
 }
 
-struct expand_data {
-   struct object_id oid;
-   enum object_type type;
-   unsigned long size;
-   off_t disk_size;
-   const char *rest;
-   struct object_id delta_base_oid;
-
-   /*
-* If mark_query is true, we do not expand anything, but rather
-* just mark the object_info with items we wish to query.
-*/
-   int mark_query;
-
-   /*
-* Whether to split the input on whitespace before feeding it to
-* get_sha1; this is decided during the mark_query phase based on
-* whether we have a %(rest) token in our format.
-*/
-   int split_on_whitespace;
-
-   /*
-* After a mark_query run, this object_info is set up to be
-* passed to sha1_object_info_extended. It will point to the data
-* elements above, so you can retrieve the response from there.
-*/
-   struct object_info info;
-
-   /*
-* This flag will be true if the requested batch format and options
-* don't require us to call sha1_object_info, which can then be
-* optimized out.
-*/
-   unsigned skip_object_info : 1;
-};
-
 static int is_atom(const char *atom, const char *s, int slen)
 {
int alen = strlen(atom);
diff --git a/ref-filter.h b/ref-filter.h
index 0d98342b34319..16d00e4b1bded 100644
--- a/ref-filter.h
+++ b/ref-filter.h
@@ -72,6 +72,42 @@ struct ref_filter {
verbose;
 };
 
+struct expand_data {
+   struct object_id oid;
+   enum object_type type;
+   unsigned long size;
+   off_t disk_size;
+   const char *rest;
+   struct object_id delta_base_oid;
+
+   /*
+* If mark_query is true, we do not expand anything, but rather
+* just mark the object_info with items we wish to query.
+*/
+   int mark_query;
+
+   /*
+* Whether to split the input on whitespace before feeding it to
+* get_sha1; this is decided during the mark_query phase based on
+* whether we have a %(rest) token in our format.
+*/
+   int split_on_whitespace;
+
+   /*
+* After a mark_query run, this object_info is set up to be
+* passed to sha1_object_info_extended. It will point to the data
+* elements above, so you can retrieve the response from there.
+*/
+   struct object_info info;
+
+   /*
+* This flag will be true if the requested batch format and options
+* don't require us to call sha1_object_info, which can then be
+* optimized out.
+*/
+   unsigned skip_object_info : 1;
+};
+
 struct ref_format {
/*
 * Set these to define the format; make sure you call

--
https://github.com/git/git/pull/450


[PATCH 04/20] cat-file: make valid_atoms as a function parameter

2018-01-09 Thread Olga Telezhnaya
Make valid_atoms as a function parameter,
there could be another variable further.
Need that for further reusing of formatting logic in cat-file.c.

Signed-off-by: Olga Telezhnaia 
Mentored-by: Christian Couder 
Mentored by: Jeff King 
---
 ref-filter.c | 15 ++-
 1 file changed, 10 insertions(+), 5 deletions(-)

diff --git a/ref-filter.c b/ref-filter.c
index 1426f0c28bce7..2d6e81fe1ab00 100644
--- a/ref-filter.c
+++ b/ref-filter.c
@@ -396,6 +396,7 @@ struct atom_value {
  * Used to parse format string and sort specifiers
  */
 static int parse_ref_filter_atom(const struct ref_format *format,
+const struct valid_atom *valid_atoms, int 
n_atoms,
 const char *atom, const char *ep)
 {
const char *sp;
@@ -425,13 +426,13 @@ static int parse_ref_filter_atom(const struct ref_format 
*format,
atom_len = (arg ? arg : ep) - sp;
 
/* Is the atom a valid one? */
-   for (i = 0; i < ARRAY_SIZE(valid_atoms); i++) {
+   for (i = 0; i < n_atoms; i++) {
int len = strlen(valid_atoms[i].name);
if (len == atom_len && !memcmp(valid_atoms[i].name, sp, len))
break;
}
 
-   if (ARRAY_SIZE(valid_atoms) <= i)
+   if (n_atoms <= i)
die(_("unknown field name: %.*s"), (int)(ep-atom), atom);
 
/* Add it in, including the deref prefix */
@@ -708,7 +709,8 @@ int verify_ref_format(struct ref_format *format)
if (!ep)
return error(_("malformed format string %s"), sp);
/* sp points at "%(" and ep points at the closing ")" */
-   at = parse_ref_filter_atom(format, sp + 2, ep);
+   at = parse_ref_filter_atom(format, valid_atoms,
+  ARRAY_SIZE(valid_atoms), sp + 2, ep);
cp = ep + 1;
 
if (skip_prefix(used_atoms[at].name, "color:", ))
@@ -2139,7 +2141,9 @@ void format_ref_array_item(struct ref_array_item *info,
if (cp < sp)
append_literal(cp, sp, );
get_ref_atom_value(info,
-  parse_ref_filter_atom(format, sp + 2, ep),
+  parse_ref_filter_atom(format, valid_atoms,
+
ARRAY_SIZE(valid_atoms),
+sp + 2, ep),
   );
atomv->handler(atomv, );
}
@@ -2187,7 +2191,8 @@ static int parse_sorting_atom(const char *atom)
 */
struct ref_format dummy = REF_FORMAT_INIT;
const char *end = atom + strlen(atom);
-   return parse_ref_filter_atom(, atom, end);
+   return parse_ref_filter_atom(, valid_atoms,
+ARRAY_SIZE(valid_atoms), atom, end);
 }
 
 /*  If no sorting option is given, use refname to sort as default */

--
https://github.com/git/git/pull/450


[PATCH 15/20] cat-file: start reusing populate_value

2018-01-09 Thread Olga Telezhnaya
Move logic related to getting object info from cat-file to ref-filter.
It will help to reuse whole formatting logic from ref-filter further.

Signed-off-by: Olga Telezhnaia 
Mentored-by: Christian Couder 
Mentored by: Jeff King 
---
 builtin/cat-file.c | 16 +++-
 ref-filter.c   | 15 +++
 ref-filter.h   |  2 ++
 3 files changed, 20 insertions(+), 13 deletions(-)

diff --git a/builtin/cat-file.c b/builtin/cat-file.c
index 1c92194faaede..e11dbf88e386c 100644
--- a/builtin/cat-file.c
+++ b/builtin/cat-file.c
@@ -284,21 +284,11 @@ static void batch_object_write(const char *obj_name, 
struct batch_options *opt,
struct strbuf buf = STRBUF_INIT;
struct ref_array_item item;
 
-   if (!data->skip_object_info &&
-   sha1_object_info_extended(data->oid.hash, >info,
- OBJECT_INFO_LOOKUP_REPLACE) < 0) {
-   printf("%s missing\n",
-  obj_name ? obj_name : oid_to_hex(>oid));
-   fflush(stdout);
-   return;
-   }
-
item.objectname = data->oid;
-   item.type = data->type;
-   item.size = data->size;
-   item.disk_size = data->disk_size;
item.rest = data->rest;
-   item.delta_base_oid = data->delta_base_oid;
+   item.start_of_request = obj_name;
+
+   if (populate_value()) return;
 
strbuf_expand(, opt->format->format, expand_format, );
strbuf_addch(, '\n');
diff --git a/ref-filter.c b/ref-filter.c
index ed1b78943b8b4..7df6d7e3d6511 100644
--- a/ref-filter.c
+++ b/ref-filter.c
@@ -1469,6 +1469,21 @@ int populate_value(struct ref_array_item *ref)
ref->symref = "";
}
 
+   if (cat_file_info) {
+   if (!cat_file_info->skip_object_info &&
+   sha1_object_info_extended(ref->objectname.hash, 
_file_info->info,
+ OBJECT_INFO_LOOKUP_REPLACE) < 0) {
+   const char *e = ref->start_of_request;
+   printf("%s missing\n", e ? e : 
oid_to_hex(>objectname));
+   fflush(stdout);
+   return -1;
+   }
+   ref->type = cat_file_info->type;
+   ref->size = cat_file_info->size;
+   ref->disk_size = cat_file_info->disk_size;
+   ref->delta_base_oid = cat_file_info->delta_base_oid;
+   }
+
/* Fill in specials first */
for (i = 0; i < used_atom_cnt; i++) {
struct used_atom *atom = _atoms[i];
diff --git a/ref-filter.h b/ref-filter.h
index d541749f9b1dc..9ecf3ef9a 100644
--- a/ref-filter.h
+++ b/ref-filter.h
@@ -45,6 +45,8 @@ struct ref_array_item {
off_t disk_size;
const char *rest;
struct object_id delta_base_oid;
+   /* Need it for better explanation in error log. */
+   const char *start_of_request;
char refname[FLEX_ARRAY];
 };
 

--
https://github.com/git/git/pull/450


[PATCH 19/20] cat-file: move skip_object_info into ref-filter

2018-01-09 Thread Olga Telezhnaya
Move logic related to skip_object_info into ref-filter,
so that cat-file does not use that field at all.

Signed-off-by: Olga Telezhnaia 
Mentored-by: Christian Couder 
Mentored by: Jeff King 
---
 builtin/cat-file.c | 7 +--
 ref-filter.c   | 5 +
 ref-filter.h   | 1 +
 3 files changed, 7 insertions(+), 6 deletions(-)

diff --git a/builtin/cat-file.c b/builtin/cat-file.c
index 5aac10b9808ff..19cee0d22fabe 100644
--- a/builtin/cat-file.c
+++ b/builtin/cat-file.c
@@ -395,16 +395,11 @@ static int batch_objects(struct batch_options *opt)
opt->format->cat_file_data = 
opt->format->is_cat = 1;
opt->format->split_on_whitespace = _on_whitespace;
+   opt->format->all_objects = opt->all_objects;
verify_ref_format(opt->format);
if (opt->cmdmode)
data.split_on_whitespace = 1;
 
-   if (opt->all_objects) {
-   struct object_info empty = OBJECT_INFO_INIT;
-   if (!memcmp(, , sizeof(empty)))
-   data.skip_object_info = 1;
-   }
-
/*
 * If we are printing out the object, then always fill in the type,
 * since we will want to decide whether or not to stream.
diff --git a/ref-filter.c b/ref-filter.c
index ee27edb2dad56..dbca6856432c0 100644
--- a/ref-filter.c
+++ b/ref-filter.c
@@ -766,6 +766,11 @@ int verify_ref_format(struct ref_format *format)
}
if (format->need_color_reset_at_eol && !want_color(format->use_color))
format->need_color_reset_at_eol = 0;
+   if (is_cat && format->all_objects) {
+   struct object_info empty = OBJECT_INFO_INIT;
+   if (!memcmp(_file_info->info, , sizeof(empty)))
+   cat_file_info->skip_object_info = 1;
+   }
return 0;
 }
 
diff --git a/ref-filter.h b/ref-filter.h
index 3228661414623..7f7b17e659241 100644
--- a/ref-filter.h
+++ b/ref-filter.h
@@ -128,6 +128,7 @@ struct ref_format {
struct expand_data *cat_file_data;
int is_cat;
int *split_on_whitespace;
+   int all_objects;
 };
 
 #define REF_FORMAT_INIT { NULL, 0, -1 }

--
https://github.com/git/git/pull/450


[PATCH 14/20] cat-file: make populate_value global

2018-01-09 Thread Olga Telezhnaya
Make function global for further using in cat-file.
Also added return value for handling errors.

Signed-off-by: Olga Telezhnaia 
Mentored-by: Christian Couder 
Mentored by: Jeff King 
---
 ref-filter.c | 4 ++--
 ref-filter.h | 3 +++
 2 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/ref-filter.c b/ref-filter.c
index 56d2687e07df9..ed1b78943b8b4 100644
--- a/ref-filter.c
+++ b/ref-filter.c
@@ -1456,7 +1456,7 @@ static void need_object(struct ref_array_item *ref) {
 /*
  * Parse the object referred by ref, and grab needed value.
  */
-static void populate_value(struct ref_array_item *ref)
+int populate_value(struct ref_array_item *ref)
 {
int i;
 
@@ -1577,7 +1577,7 @@ static void populate_value(struct ref_array_item *ref)
break;
}
}
-   return;
+   return 0;
 }
 
 /*
diff --git a/ref-filter.h b/ref-filter.h
index 28774e8e0f771..d541749f9b1dc 100644
--- a/ref-filter.h
+++ b/ref-filter.h
@@ -176,4 +176,7 @@ void setup_ref_filter_porcelain_msg(void);
 void pretty_print_ref(const char *name, const unsigned char *sha1,
  const struct ref_format *format);
 
+/* Fill the values of request and prepare all data for final string creation */
+int populate_value(struct ref_array_item *ref);
+
 #endif /*  REF_FILTER_H  */

--
https://github.com/git/git/pull/450


[PATCH 09/20] cat-file: get rid of goto in ref-filter

2018-01-09 Thread Olga Telezhnaya
Get rid of goto command in ref-filter for better readability.

Signed-off-by: Olga Telezhnaia 
Mentored-by: Christian Couder 
Mentored by: Jeff King 
---
 ref-filter.c | 103 ++-
 1 file changed, 53 insertions(+), 50 deletions(-)

diff --git a/ref-filter.c b/ref-filter.c
index 2bd9a8fc4e39c..1b8c8787190a9 100644
--- a/ref-filter.c
+++ b/ref-filter.c
@@ -1405,16 +1405,60 @@ static const char *get_refname(struct used_atom *atom, 
struct ref_array_item *re
return show_ref(>u.refname, ref->refname);
 }
 
+static void need_object(struct ref_array_item *ref) {
+   struct object *obj;
+   const struct object_id *tagged;
+   unsigned long size;
+   int eaten;
+   void *buf = get_obj(>objectname, , , );
+   if (!buf)
+   die(_("missing object %s for %s"),
+   oid_to_hex(>objectname), ref->refname);
+   if (!obj)
+   die(_("parse_object_buffer failed on %s for %s"),
+   oid_to_hex(>objectname), ref->refname);
+
+   grab_values(ref->value, 0, obj, buf, size);
+   if (!eaten)
+   free(buf);
+
+   /*
+* If there is no atom that wants to know about tagged
+* object, we are done.
+*/
+   if (!need_tagged || (obj->type != OBJ_TAG))
+   return;
+
+   /*
+* If it is a tag object, see if we use a value that derefs
+* the object, and if we do grab the object it refers to.
+*/
+   tagged = &((struct tag *)obj)->tagged->oid;
+
+   /*
+* NEEDSWORK: This derefs tag only once, which
+* is good to deal with chains of trust, but
+* is not consistent with what deref_tag() does
+* which peels the onion to the core.
+*/
+   buf = get_obj(tagged, , , );
+   if (!buf)
+   die(_("missing object %s for %s"),
+   oid_to_hex(tagged), ref->refname);
+   if (!obj)
+   die(_("parse_object_buffer failed on %s for %s"),
+   oid_to_hex(tagged), ref->refname);
+   grab_values(ref->value, 1, obj, buf, size);
+   if (!eaten)
+   free(buf);
+}
+
 /*
  * Parse the object referred by ref, and grab needed value.
  */
 static void populate_value(struct ref_array_item *ref)
 {
-   void *buf;
-   struct object *obj;
-   int eaten, i;
-   unsigned long size;
-   const struct object_id *tagged;
+   int i;
 
ref->value = xcalloc(used_atom_cnt, sizeof(struct atom_value));
 
@@ -1528,53 +1572,12 @@ static void populate_value(struct ref_array_item *ref)
 
for (i = 0; i < used_atom_cnt; i++) {
struct atom_value *v = >value[i];
-   if (v->s == NULL)
-   goto need_obj;
+   if (v->s == NULL) {
+   need_object(ref);
+   break;
+   }
}
return;
-
- need_obj:
-   buf = get_obj(>objectname, , , );
-   if (!buf)
-   die(_("missing object %s for %s"),
-   oid_to_hex(>objectname), ref->refname);
-   if (!obj)
-   die(_("parse_object_buffer failed on %s for %s"),
-   oid_to_hex(>objectname), ref->refname);
-
-   grab_values(ref->value, 0, obj, buf, size);
-   if (!eaten)
-   free(buf);
-
-   /*
-* If there is no atom that wants to know about tagged
-* object, we are done.
-*/
-   if (!need_tagged || (obj->type != OBJ_TAG))
-   return;
-
-   /*
-* If it is a tag object, see if we use a value that derefs
-* the object, and if we do grab the object it refers to.
-*/
-   tagged = &((struct tag *)obj)->tagged->oid;
-
-   /*
-* NEEDSWORK: This derefs tag only once, which
-* is good to deal with chains of trust, but
-* is not consistent with what deref_tag() does
-* which peels the onion to the core.
-*/
-   buf = get_obj(tagged, , , );
-   if (!buf)
-   die(_("missing object %s for %s"),
-   oid_to_hex(tagged), ref->refname);
-   if (!obj)
-   die(_("parse_object_buffer failed on %s for %s"),
-   oid_to_hex(tagged), ref->refname);
-   grab_values(ref->value, 1, obj, buf, size);
-   if (!eaten)
-   free(buf);
 }
 
 /*

--
https://github.com/git/git/pull/450


[PATCH 10/20] cat-file: simplify expand_atom function

2018-01-09 Thread Olga Telezhnaya
Not sure, but looks like there is no need in that checking.
There is a checking before whether it is null and we die in such case.

Signed-off-by: Olga Telezhnaia 
Mentored-by: Christian Couder 
Mentored by: Jeff King 
---
 builtin/cat-file.c | 7 +++
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/builtin/cat-file.c b/builtin/cat-file.c
index 9055fa3a8b0ae..dd43457c0ad7e 100644
--- a/builtin/cat-file.c
+++ b/builtin/cat-file.c
@@ -193,10 +193,9 @@ static void expand_atom(struct strbuf *sb, const char 
*atom, int len,
strbuf_addf(sb, "%lu", data->size);
else if (is_atom("objectsize:disk", atom, len))
strbuf_addf(sb, "%"PRIuMAX, (uintmax_t)data->disk_size);
-   else if (is_atom("rest", atom, len)) {
-   if (data->rest)
-   strbuf_addstr(sb, data->rest);
-   } else if (is_atom("deltabase", atom, len))
+   else if (is_atom("rest", atom, len))
+   strbuf_addstr(sb, data->rest);
+   else if (is_atom("deltabase", atom, len))
strbuf_addstr(sb, oid_to_hex(>delta_base_oid));
else
die("unknown format element: %.*s", len, atom);

--
https://github.com/git/git/pull/450


[PATCH 11/20] cat-file: get rid of duplicate checking

2018-01-09 Thread Olga Telezhnaya
We could remove this because we have already checked that
at verify_ref_format function in ref-filter.

Signed-off-by: Olga Telezhnaia 
Mentored-by: Christian Couder 
Mentored by: Jeff King 
---
 builtin/cat-file.c | 2 --
 1 file changed, 2 deletions(-)

diff --git a/builtin/cat-file.c b/builtin/cat-file.c
index dd43457c0ad7e..1f331559e55c7 100644
--- a/builtin/cat-file.c
+++ b/builtin/cat-file.c
@@ -197,8 +197,6 @@ static void expand_atom(struct strbuf *sb, const char 
*atom, int len,
strbuf_addstr(sb, data->rest);
else if (is_atom("deltabase", atom, len))
strbuf_addstr(sb, oid_to_hex(>delta_base_oid));
-   else
-   die("unknown format element: %.*s", len, atom);
 }
 
 static size_t expand_format(struct strbuf *sb, const char *start, void *vdata)

--
https://github.com/git/git/pull/450


[PATCH RFC 19/24] ref-filter: make populate_value internal again

2018-01-26 Thread Olga Telezhnaya
Remove populate_value from header file. We needed that
for interim step, now it could be returned back.

Signed-off-by: Olga Telezhnaia 
Mentored-by: Christian Couder 
Mentored by: Jeff King 
---
 ref-filter.c | 2 +-
 ref-filter.h | 3 ---
 2 files changed, 1 insertion(+), 4 deletions(-)

diff --git a/ref-filter.c b/ref-filter.c
index 4d0d4f081227d..c3a5c3897295f 100644
--- a/ref-filter.c
+++ b/ref-filter.c
@@ -1476,7 +1476,7 @@ static int check_and_fill_for_cat(struct ref_array_item 
*ref)
 /*
  * Parse the object referred by ref, and grab needed value.
  */
-int populate_value(struct ref_array_item *ref)
+static int populate_value(struct ref_array_item *ref)
 {
int i;
 
diff --git a/ref-filter.h b/ref-filter.h
index d8064086f36a9..285a2311f6cc9 100644
--- a/ref-filter.h
+++ b/ref-filter.h
@@ -172,9 +172,6 @@ void setup_ref_filter_porcelain_msg(void);
 void pretty_print_ref(const char *name, const unsigned char *sha1,
  const struct ref_format *format);
 
-/* Fill the values of request and prepare all data for final string creation */
-int populate_value(struct ref_array_item *ref);
-
 /* Search for atom "rest" in given format. */
 int is_rest_atom_used(const struct ref_format *format);
 

--
https://github.com/git/git/pull/452


[PATCH RFC 20/24] ref-filter: unifying formatting of cat-file opts

2018-01-26 Thread Olga Telezhnaya
cat-file options are now filled by general logic.

Signed-off-by: Olga Telezhnaia 
Mentored-by: Christian Couder 
Mentored by: Jeff King 
---
 ref-filter.c | 31 ++-
 1 file changed, 14 insertions(+), 17 deletions(-)

diff --git a/ref-filter.c b/ref-filter.c
index c3a5c3897295f..2cac394e93f52 100644
--- a/ref-filter.c
+++ b/ref-filter.c
@@ -825,8 +825,10 @@ static void grab_common_values(struct atom_value *val, int 
deref, struct object
else if (!strcmp(name, "objectsize")) {
v->value = sz;
v->s = xstrfmt("%lu", sz);
-   }
-   else if (deref)
+   } else if (!strcmp(name, "objectsize:disk")) {
+   v->value = cat_file_info.disk_size;
+   v->s = xstrfmt("%"PRIuMAX, (uintmax_t)v->value);
+   } else if (deref)
grab_objectname(name, obj->oid.hash, v, _atom[i]);
}
 }
@@ -1509,21 +1511,7 @@ static int populate_value(struct ref_array_item *ref)
name++;
}
 
-   if (is_cat) {
-   if (starts_with(name, "objectname"))
-   v->s = oid_to_hex(>objectname);
-   else if (starts_with(name, "objecttype"))
-   v->s = typename(ref->type);
-   else if (starts_with(name, "objectsize")) {
-   v->s = xstrfmt("%lu", ref->size);
-   } else if (starts_with(name, "objectsize:disk")) {
-   v->s = xstrfmt("%"PRIuMAX, 
(uintmax_t)ref->disk_size);
-   } else if (starts_with(name, "rest"))
-   v->s = ref->rest;
-   else if (starts_with(name, "deltabase"))
-   v->s = xstrdup(oid_to_hex(ref->delta_base_oid));
-   continue;
-   } else if (starts_with(name, "refname"))
+   if (starts_with(name, "refname"))
refname = get_refname(atom, ref);
else if (starts_with(name, "symref"))
refname = get_symref(atom, ref);
@@ -1579,6 +1567,15 @@ static int populate_value(struct ref_array_item *ref)
else
v->s = " ";
continue;
+   } else if (starts_with(name, "rest")) {
+   v->s = ref->rest ? ref->rest : "";
+   continue;
+   } else if (starts_with(name, "deltabase")) {
+   if (ref->delta_base_oid)
+   v->s = xstrdup(oid_to_hex(ref->delta_base_oid));
+   else
+   v->s = "";
+   continue;
} else if (starts_with(name, "align")) {
v->handler = align_atom_handler;
continue;

--
https://github.com/git/git/pull/452


[PATCH RFC 13/24] ref-filter: add is_cat flag

2018-01-26 Thread Olga Telezhnaya
Add is_cat flag, further it helps to get rid of cat_file_data field
in ref_format.

Signed-off-by: Olga Telezhnaia 
Mentored-by: Christian Couder 
Mentored by: Jeff King 
---
 builtin/cat-file.c | 1 +
 ref-filter.c   | 8 +---
 ref-filter.h   | 1 +
 3 files changed, 7 insertions(+), 3 deletions(-)

diff --git a/builtin/cat-file.c b/builtin/cat-file.c
index c2ca645662ae7..8f34d085962ed 100644
--- a/builtin/cat-file.c
+++ b/builtin/cat-file.c
@@ -394,6 +394,7 @@ static int batch_objects(struct batch_options *opt)
 */
memset(, 0, sizeof(data));
opt->format.cat_file_data = 
+   opt->format.is_cat = 1;
verify_ref_format(>format);
if (opt->cmdmode)
data.split_on_whitespace = 1;
diff --git a/ref-filter.c b/ref-filter.c
index 8d10d356609e7..3b61e790e90d1 100644
--- a/ref-filter.c
+++ b/ref-filter.c
@@ -101,6 +101,7 @@ static struct used_atom {
 } *used_atom;
 static int used_atom_cnt, need_tagged, need_symref;
 struct expand_data *cat_file_info;
+static int is_cat = 0;
 
 static void color_atom_parser(const struct ref_format *format, struct 
used_atom *atom, const char *color_value)
 {
@@ -493,7 +494,7 @@ static int parse_ref_filter_atom(const struct ref_format 
*format,
need_tagged = 1;
if (!strcmp(valid_atom[i].name, "symref"))
need_symref = 1;
-   if (cat_file_info && !strcmp(valid_atom[i].name, "rest"))
+   if (is_cat && !strcmp(valid_atom[i].name, "rest"))
cat_file_info->split_on_whitespace = 1;
return at;
 }
@@ -739,6 +740,7 @@ int verify_ref_format(struct ref_format *format)
const char *cp, *sp;
 
cat_file_info = format->cat_file_data;
+   is_cat = format->is_cat;
format->need_color_reset_at_eol = 0;
for (cp = format->format; *cp && (sp = find_next(cp)); ) {
const char *color, *ep = strchr(sp, ')');
@@ -748,7 +750,7 @@ int verify_ref_format(struct ref_format *format)
return error(_("malformed format string %s"), sp);
/* sp points at "%(" and ep points at the closing ")" */
 
-   if (format->cat_file_data) {
+   if (is_cat) {
at = parse_ref_filter_atom(format, valid_cat_file_atom,
   
ARRAY_SIZE(valid_cat_file_atom), sp + 2, ep);
} else {
@@ -1481,7 +1483,7 @@ int populate_value(struct ref_array_item *ref)
ref->symref = "";
}
 
-   if (cat_file_info && check_and_fill_for_cat(ref))
+   if (is_cat && check_and_fill_for_cat(ref))
return -1;
 
/* Fill in specials first */
diff --git a/ref-filter.h b/ref-filter.h
index e41d2913c0fff..c848370bed84a 100644
--- a/ref-filter.h
+++ b/ref-filter.h
@@ -126,6 +126,7 @@ struct ref_format {
 * hopefully would be reduced later.
 */
struct expand_data *cat_file_data;
+   int is_cat;
 };
 
 #define REF_FORMAT_INIT { NULL, 0, -1 }

--
https://github.com/git/git/pull/452


[PATCH RFC 03/24] cat-file: split expand_atom into 2 functions

2018-01-26 Thread Olga Telezhnaya
Split expand_atom function into 2 different functions,
expand_atom_into_fields prepares variable for further filling,
(new) expand_atom creates resulting string.
Need that for further reusing of formatting logic from ref-filter.

Signed-off-by: Olga Telezhnaia 
Mentored-by: Christian Couder 
Mentored by: Jeff King 
---
 builtin/cat-file.c | 73 +-
 1 file changed, 39 insertions(+), 34 deletions(-)

diff --git a/builtin/cat-file.c b/builtin/cat-file.c
index f5fa4fd75af26..f783b39b9bd5c 100644
--- a/builtin/cat-file.c
+++ b/builtin/cat-file.c
@@ -217,47 +217,49 @@ static int is_atom(const char *atom, const char *s, int 
slen)
return alen == slen && !memcmp(atom, s, alen);
 }
 
-static void expand_atom(struct strbuf *sb, const char *atom, int len,
-   void *vdata)
+static void expand_atom_into_fields(struct strbuf *sb, const char *atom, int 
len,
+   struct expand_data *data)
 {
-   struct expand_data *data = vdata;
+   if (is_atom("objectname", atom, len))
+   ; /* do nothing */
+   else if (is_atom("objecttype", atom, len))
+   data->info.typep = >type;
+   else if (is_atom("objectsize", atom, len))
+   data->info.sizep = >size;
+   else if (is_atom("objectsize:disk", atom, len))
+   data->info.disk_sizep = >disk_size;
+   else if (is_atom("rest", atom, len))
+   data->split_on_whitespace = 1;
+   else if (is_atom("deltabase", atom, len))
+   data->info.delta_base_sha1 = data->delta_base_oid.hash;
+   else
+   die("unknown format element: %.*s", len, atom);
+}
 
-   if (is_atom("objectname", atom, len)) {
-   if (!data->mark_query)
-   strbuf_addstr(sb, oid_to_hex(>oid));
-   } else if (is_atom("objecttype", atom, len)) {
-   if (data->mark_query)
-   data->info.typep = >type;
-   else
-   strbuf_addstr(sb, typename(data->type));
-   } else if (is_atom("objectsize", atom, len)) {
-   if (data->mark_query)
-   data->info.sizep = >size;
-   else
-   strbuf_addf(sb, "%lu", data->size);
-   } else if (is_atom("objectsize:disk", atom, len)) {
-   if (data->mark_query)
-   data->info.disk_sizep = >disk_size;
-   else
-   strbuf_addf(sb, "%"PRIuMAX, (uintmax_t)data->disk_size);
-   } else if (is_atom("rest", atom, len)) {
-   if (data->mark_query)
-   data->split_on_whitespace = 1;
-   else if (data->rest)
+static void expand_atom(struct strbuf *sb, const char *atom, int len,
+struct expand_data *data)
+{
+   if (is_atom("objectname", atom, len))
+   strbuf_addstr(sb, oid_to_hex(>oid));
+   else if (is_atom("objecttype", atom, len))
+   strbuf_addstr(sb, typename(data->type));
+   else if (is_atom("objectsize", atom, len))
+   strbuf_addf(sb, "%lu", data->size);
+   else if (is_atom("objectsize:disk", atom, len))
+   strbuf_addf(sb, "%"PRIuMAX, (uintmax_t)data->disk_size);
+   else if (is_atom("rest", atom, len)) {
+   if (data->rest)
strbuf_addstr(sb, data->rest);
-   } else if (is_atom("deltabase", atom, len)) {
-   if (data->mark_query)
-   data->info.delta_base_sha1 = data->delta_base_oid.hash;
-   else
-   strbuf_addstr(sb,
- oid_to_hex(>delta_base_oid));
-   } else
+   } else if (is_atom("deltabase", atom, len))
+   strbuf_addstr(sb, oid_to_hex(>delta_base_oid));
+   else
die("unknown format element: %.*s", len, atom);
 }
 
-static size_t expand_format(struct strbuf *sb, const char *start, void *data)
+static size_t expand_format(struct strbuf *sb, const char *start, void *vdata)
 {
const char *end;
+   struct expand_data *data = vdata;
 
if (*start != '(')
return 0;
@@ -265,7 +267,10 @@ static size_t expand_format(struct strbuf *sb, const char 
*start, void *data)
if (!end)
die("format element '%s' does not end in ')'", start);
 
-   expand_atom(sb, start + 1, end - start - 1, data);
+   if (data->mark_query)
+   expand_atom_into_fields(sb, start + 1, end - start - 1, data);
+   else
+   expand_atom(sb, start + 1, end - start - 1, data);
 
return end - start + 1;
 }

--
https://github.com/git/git/pull/452


[PATCH RFC 16/24] ref-filter: make cat_file_info independent

2018-01-26 Thread Olga Telezhnaya
Remove connection between expand_data variable
in cat-file and in ref-filter.
It will help further to get rid of using expand_data in cat-file.

Signed-off-by: Olga Telezhnaia 
Mentored-by: Christian Couder 
Mentored by: Jeff King 
---
 builtin/cat-file.c |  2 +-
 ref-filter.c   | 29 +++--
 ref-filter.h   |  1 -
 3 files changed, 16 insertions(+), 16 deletions(-)

diff --git a/builtin/cat-file.c b/builtin/cat-file.c
index 3a52c551f366a..bd803856537b8 100644
--- a/builtin/cat-file.c
+++ b/builtin/cat-file.c
@@ -290,6 +290,7 @@ static void batch_object_write(const char *obj_name, struct 
batch_options *opt,
item.start_of_request = obj_name;
 
if (populate_value()) return;
+   data->type = item.type;
 
strbuf_expand(, opt->format.format, expand_format, );
strbuf_addch(, '\n');
@@ -392,7 +393,6 @@ static int batch_objects(struct batch_options *opt)
 * object.
 */
memset(, 0, sizeof(data));
-   opt->format.cat_file_data = 
opt->format.is_cat = 1;
opt->format.all_objects = opt->all_objects;
verify_ref_format(>format);
diff --git a/ref-filter.c b/ref-filter.c
index 29a1b75c93181..906a5344949f7 100644
--- a/ref-filter.c
+++ b/ref-filter.c
@@ -100,7 +100,7 @@ static struct used_atom {
} u;
 } *used_atom;
 static int used_atom_cnt, need_tagged, need_symref;
-struct expand_data *cat_file_info;
+struct expand_data cat_file_info;
 static int is_cat = 0;
 
 static void color_atom_parser(const struct ref_format *format, struct 
used_atom *atom, const char *color_value)
@@ -256,9 +256,9 @@ static void objectname_atom_parser(const struct ref_format 
*format, struct used_
 static void objectsize_atom_parser(const struct ref_format *format, struct 
used_atom *atom, const char *arg)
 {
if (!arg)
-   cat_file_info->info.sizep = _file_info->size;
+   cat_file_info.info.sizep = _file_info.size;
else if (!strcmp(arg, "disk"))
-   cat_file_info->info.disk_sizep = _file_info->disk_size;
+   cat_file_info.info.disk_sizep = _file_info.disk_size;
else
die(_("urecognized %%(objectsize) argument: %s"), arg);
 }
@@ -266,7 +266,7 @@ static void objectsize_atom_parser(const struct ref_format 
*format, struct used_
 static void objecttype_atom_parser(const struct ref_format *format, struct 
used_atom *atom, const char *arg)
 {
if (!arg)
-   cat_file_info->info.typep = _file_info->type;
+   cat_file_info.info.typep = _file_info.type;
else
die(_("urecognized %%(objecttype) argument: %s"), arg);
 }
@@ -274,7 +274,7 @@ static void objecttype_atom_parser(const struct ref_format 
*format, struct used_
 static void deltabase_atom_parser(const struct ref_format *format, struct 
used_atom *atom, const char *arg)
 {
if (!arg)
-   cat_file_info->info.delta_base_sha1 = 
cat_file_info->delta_base_oid.hash;
+   cat_file_info.info.delta_base_sha1 = 
cat_file_info.delta_base_oid.hash;
else
die(_("urecognized %%(deltabase) argument: %s"), arg);
 }
@@ -752,7 +752,6 @@ int verify_ref_format(struct ref_format *format)
 {
const char *cp, *sp;
 
-   cat_file_info = format->cat_file_data;
is_cat = format->is_cat;
format->need_color_reset_at_eol = 0;
for (cp = format->format; *cp && (sp = find_next(cp)); ) {
@@ -779,8 +778,8 @@ int verify_ref_format(struct ref_format *format)
format->need_color_reset_at_eol = 0;
if (is_cat && format->all_objects) {
struct object_info empty = OBJECT_INFO_INIT;
-   if (!memcmp(_file_info->info, , sizeof(empty)))
-   cat_file_info->skip_object_info = 1;
+   if (!memcmp(_file_info.info, , sizeof(empty)))
+   cat_file_info.skip_object_info = 1;
}
return 0;
 }
@@ -1470,18 +1469,20 @@ static void need_object(struct ref_array_item *ref) {
 
 static int check_and_fill_for_cat(struct ref_array_item *ref)
 {
-   if (!cat_file_info->skip_object_info &&
-   sha1_object_info_extended(ref->objectname.hash, 
_file_info->info,
+   if (!cat_file_info.info.typep)
+   cat_file_info.info.typep = _file_info.type;
+   if (!cat_file_info.skip_object_info &&
+   sha1_object_info_extended(ref->objectname.hash, _file_info.info,
  OBJECT_INFO_LOOKUP_REPLACE) < 0) {
const char *e = ref->start_of_request;
printf("%s missing\n", e ? e : oid_to_hex(>objectname));
fflush(stdout);
return -1;
}
-   ref->type = cat_file_info->type;
-   ref->size = cat_file_info->size;
-   ref->disk_size = cat_file_info->disk_size;
-   ref->delta_base_oid = 

[PATCH RFC 14/24] ref_filter: add is_rest_atom_used function

2018-01-26 Thread Olga Telezhnaya
Delete all items related to split_on_whitespace from ref-filter
and add new function for handling the logic.
Now cat-file could invoke that function to implementing its logic.

Signed-off-by: Olga Telezhnaia 
Mentored-by: Christian Couder 
Mentored by: Jeff King 
---
 builtin/cat-file.c |  8 +++-
 ref-filter.c   | 17 +++--
 ref-filter.h   | 10 +++---
 3 files changed, 21 insertions(+), 14 deletions(-)

diff --git a/builtin/cat-file.c b/builtin/cat-file.c
index 8f34d085962ed..601a87d9b5f7c 100644
--- a/builtin/cat-file.c
+++ b/builtin/cat-file.c
@@ -381,8 +381,7 @@ static int batch_objects(struct batch_options *opt)
 {
struct strbuf buf = STRBUF_INIT;
struct expand_data data;
-   int save_warning;
-   int retval = 0;
+   int save_warning, is_rest, retval = 0;
 
if (!opt->format.format)
opt->format.format = "%(objectname) %(objecttype) 
%(objectsize)";
@@ -396,8 +395,6 @@ static int batch_objects(struct batch_options *opt)
opt->format.cat_file_data = 
opt->format.is_cat = 1;
verify_ref_format(>format);
-   if (opt->cmdmode)
-   data.split_on_whitespace = 1;
 
if (opt->all_objects) {
struct object_info empty = OBJECT_INFO_INIT;
@@ -436,9 +433,10 @@ static int batch_objects(struct batch_options *opt)
 */
save_warning = warn_on_object_refname_ambiguity;
warn_on_object_refname_ambiguity = 0;
+   is_rest = opt->cmdmode || is_rest_atom_used(>format);
 
while (strbuf_getline(, stdin) != EOF) {
-   if (data.split_on_whitespace) {
+   if (is_rest) {
/*
 * Split at first whitespace, tying off the beginning
 * of the string and saving the remainder (or NULL) in
diff --git a/ref-filter.c b/ref-filter.c
index 3b61e790e90d1..51da76dc21136 100644
--- a/ref-filter.c
+++ b/ref-filter.c
@@ -494,8 +494,6 @@ static int parse_ref_filter_atom(const struct ref_format 
*format,
need_tagged = 1;
if (!strcmp(valid_atom[i].name, "symref"))
need_symref = 1;
-   if (is_cat && !strcmp(valid_atom[i].name, "rest"))
-   cat_file_info->split_on_whitespace = 1;
return at;
 }
 
@@ -731,6 +729,21 @@ static const char *find_next(const char *cp)
return NULL;
 }
 
+/* Search for atom "rest" in given format. */
+int is_rest_atom_used(const struct ref_format *format)
+{
+   const char *cp, *sp;
+   for (cp = format->format; *cp && (sp = find_next(cp)); ) {
+   const char *ep = strchr(sp, ')');
+   int atom_len = ep - sp - 2;
+   sp += 2;
+   if (atom_len == 4 && !memcmp(sp, "rest", atom_len))
+   return 1;
+   cp = ep + 1;
+   }
+   return 0;
+}
+
 /*
  * Make sure the format string is well formed, and parse out
  * the used atoms.
diff --git a/ref-filter.h b/ref-filter.h
index c848370bed84a..276de387f3bd0 100644
--- a/ref-filter.h
+++ b/ref-filter.h
@@ -87,13 +87,6 @@ struct expand_data {
const char *rest;
struct object_id delta_base_oid;
 
-   /*
-* Whether to split the input on whitespace before feeding it to
-* get_sha1; this is decided during the mark_query phase based on
-* whether we have a %(rest) token in our format.
-*/
-   int split_on_whitespace;
-
/*
 * After a mark_query run, this object_info is set up to be
 * passed to sha1_object_info_extended. It will point to the data
@@ -182,4 +175,7 @@ void pretty_print_ref(const char *name, const unsigned char 
*sha1,
 /* Fill the values of request and prepare all data for final string creation */
 int populate_value(struct ref_array_item *ref);
 
+/* Search for atom "rest" in given format. */
+int is_rest_atom_used(const struct ref_format *format);
+
 #endif /*  REF_FILTER_H  */

--
https://github.com/git/git/pull/452


[PATCH RFC 18/24] ref-filter: make valid_atom general again

2018-01-26 Thread Olga Telezhnaya
Stop using valid_cat_file_atom, making the code more general.
Further commits will contain some tests, docs and
support of new features.

Signed-off-by: Olga Telezhnaia 
Mentored-by: Christian Couder 
Mentored by: Jeff King 
---
 ref-filter.c | 46 --
 1 file changed, 12 insertions(+), 34 deletions(-)

diff --git a/ref-filter.c b/ref-filter.c
index bfbc7c83fdd47..4d0d4f081227d 100644
--- a/ref-filter.c
+++ b/ref-filter.c
@@ -359,8 +359,8 @@ static struct valid_atom {
void (*parser)(const struct ref_format *format, struct used_atom *atom, 
const char *arg);
 } valid_atom[] = {
{ "refname" , FIELD_STR, refname_atom_parser },
-   { "objecttype" },
-   { "objectsize", FIELD_ULONG },
+   { "objecttype", FIELD_STR, objecttype_atom_parser },
+   { "objectsize", FIELD_ULONG, objectsize_atom_parser },
{ "objectname", FIELD_STR, objectname_atom_parser },
{ "tree" },
{ "parent" },
@@ -397,12 +397,6 @@ static struct valid_atom {
{ "if", FIELD_STR, if_atom_parser },
{ "then" },
{ "else" },
-};
-
-static struct valid_atom valid_cat_file_atom[] = {
-   { "objectname" },
-   { "objecttype", FIELD_STR, objecttype_atom_parser },
-   { "objectsize", FIELD_ULONG, objectsize_atom_parser },
{ "rest" },
{ "deltabase", FIELD_STR, deltabase_atom_parser },
 };
@@ -432,7 +426,6 @@ struct atom_value {
  * Used to parse format string and sort specifiers
  */
 static int parse_ref_filter_atom(const struct ref_format *format,
-const struct valid_atom *valid_atom, int 
n_atoms,
 const char *atom, const char *ep)
 {
const char *sp;
@@ -462,13 +455,13 @@ static int parse_ref_filter_atom(const struct ref_format 
*format,
atom_len = (arg ? arg : ep) - sp;
 
/* Is the atom a valid one? */
-   for (i = 0; i < n_atoms; i++) {
+   for (i = 0; i < ARRAY_SIZE(valid_atom); i++) {
int len = strlen(valid_atom[i].name);
if (len == atom_len && !memcmp(valid_atom[i].name, sp, len))
break;
}
 
-   if (n_atoms <= i)
+   if (ARRAY_SIZE(valid_atom) <= i)
die(_("unknown field name: %.*s"), (int)(ep-atom), atom);
 
/* Add it in, including the deref prefix */
@@ -762,15 +755,9 @@ int verify_ref_format(struct ref_format *format)
return error(_("malformed format string %s"), sp);
/* sp points at "%(" and ep points at the closing ")" */
 
-   if (is_cat) {
-   at = parse_ref_filter_atom(format, valid_cat_file_atom,
-  
ARRAY_SIZE(valid_cat_file_atom), sp + 2, ep);
-   } else {
-   at = parse_ref_filter_atom(format, valid_atom,
-  ARRAY_SIZE(valid_atom), sp + 
2, ep);
-   if (skip_prefix(used_atom[at].name, "color:", ))
-   format->need_color_reset_at_eol = 
!!strcmp(color, "reset");
-   }
+   at = parse_ref_filter_atom(format, sp + 2, ep);
+   if (skip_prefix(used_atom[at].name, "color:", ))
+   format->need_color_reset_at_eol = !!strcmp(color, 
"reset");
 
cp = ep + 1;
}
@@ -2244,18 +2231,10 @@ int format_ref_array_item(struct ref_array_item *info,
ep = strchr(sp, ')');
if (cp < sp)
append_literal(cp, sp, );
-   if (is_cat) {
-   if(get_ref_atom_value(info,
-   parse_ref_filter_atom(format, 
valid_cat_file_atom,
-   ARRAY_SIZE(valid_cat_file_atom), sp + 
2, ep),
-   ))
-   return -1;
-   } else
-   get_ref_atom_value(info,
-  parse_ref_filter_atom(format, valid_atom,
-ARRAY_SIZE(valid_atom),
-sp + 2, ep),
-  );
+   if(get_ref_atom_value(info,
+ parse_ref_filter_atom(format, sp + 2, ep),
+ ))
+   return -1;
atomv->handler(atomv, );
}
if (is_cat && strlen(format->format) == 0)
@@ -2307,8 +2286,7 @@ static int parse_sorting_atom(const char *atom)
 */
struct ref_format dummy = REF_FORMAT_INIT;
const char *end = atom + strlen(atom);
-   return parse_ref_filter_atom(, valid_atom,
-ARRAY_SIZE(valid_atom), atom, end);
+   

[PATCH RFC 01/24] ref-filter: get rid of goto

2018-01-26 Thread Olga Telezhnaya
Get rid of goto command in ref-filter for better readability.

Signed-off-by: Olga Telezhnaia 
Mentored-by: Christian Couder 
Mentored by: Jeff King 
---
 ref-filter.c | 103 ++-
 1 file changed, 53 insertions(+), 50 deletions(-)

diff --git a/ref-filter.c b/ref-filter.c
index f9e25aea7a97e..37337b57aacf4 100644
--- a/ref-filter.c
+++ b/ref-filter.c
@@ -1354,16 +1354,60 @@ static const char *get_refname(struct used_atom *atom, 
struct ref_array_item *re
return show_ref(>u.refname, ref->refname);
 }
 
+static void need_object(struct ref_array_item *ref) {
+   struct object *obj;
+   const struct object_id *tagged;
+   unsigned long size;
+   int eaten;
+   void *buf = get_obj(>objectname, , , );
+   if (!buf)
+   die(_("missing object %s for %s"),
+   oid_to_hex(>objectname), ref->refname);
+   if (!obj)
+   die(_("parse_object_buffer failed on %s for %s"),
+   oid_to_hex(>objectname), ref->refname);
+
+   grab_values(ref->value, 0, obj, buf, size);
+   if (!eaten)
+   free(buf);
+
+   /*
+* If there is no atom that wants to know about tagged
+* object, we are done.
+*/
+   if (!need_tagged || (obj->type != OBJ_TAG))
+   return;
+
+   /*
+* If it is a tag object, see if we use a value that derefs
+* the object, and if we do grab the object it refers to.
+*/
+   tagged = &((struct tag *)obj)->tagged->oid;
+
+   /*
+* NEEDSWORK: This derefs tag only once, which
+* is good to deal with chains of trust, but
+* is not consistent with what deref_tag() does
+* which peels the onion to the core.
+*/
+   buf = get_obj(tagged, , , );
+   if (!buf)
+   die(_("missing object %s for %s"),
+   oid_to_hex(tagged), ref->refname);
+   if (!obj)
+   die(_("parse_object_buffer failed on %s for %s"),
+   oid_to_hex(tagged), ref->refname);
+   grab_values(ref->value, 1, obj, buf, size);
+   if (!eaten)
+   free(buf);
+}
+
 /*
  * Parse the object referred by ref, and grab needed value.
  */
 static void populate_value(struct ref_array_item *ref)
 {
-   void *buf;
-   struct object *obj;
-   int eaten, i;
-   unsigned long size;
-   const struct object_id *tagged;
+   int i;
 
ref->value = xcalloc(used_atom_cnt, sizeof(struct atom_value));
 
@@ -1477,53 +1521,12 @@ static void populate_value(struct ref_array_item *ref)
 
for (i = 0; i < used_atom_cnt; i++) {
struct atom_value *v = >value[i];
-   if (v->s == NULL)
-   goto need_obj;
+   if (v->s == NULL) {
+   need_object(ref);
+   break;
+   }
}
return;
-
- need_obj:
-   buf = get_obj(>objectname, , , );
-   if (!buf)
-   die(_("missing object %s for %s"),
-   oid_to_hex(>objectname), ref->refname);
-   if (!obj)
-   die(_("parse_object_buffer failed on %s for %s"),
-   oid_to_hex(>objectname), ref->refname);
-
-   grab_values(ref->value, 0, obj, buf, size);
-   if (!eaten)
-   free(buf);
-
-   /*
-* If there is no atom that wants to know about tagged
-* object, we are done.
-*/
-   if (!need_tagged || (obj->type != OBJ_TAG))
-   return;
-
-   /*
-* If it is a tag object, see if we use a value that derefs
-* the object, and if we do grab the object it refers to.
-*/
-   tagged = &((struct tag *)obj)->tagged->oid;
-
-   /*
-* NEEDSWORK: This derefs tag only once, which
-* is good to deal with chains of trust, but
-* is not consistent with what deref_tag() does
-* which peels the onion to the core.
-*/
-   buf = get_obj(tagged, , , );
-   if (!buf)
-   die(_("missing object %s for %s"),
-   oid_to_hex(tagged), ref->refname);
-   if (!obj)
-   die(_("parse_object_buffer failed on %s for %s"),
-   oid_to_hex(tagged), ref->refname);
-   grab_values(ref->value, 1, obj, buf, size);
-   if (!eaten)
-   free(buf);
 }
 
 /*

--
https://github.com/git/git/pull/452


[PATCH RFC 10/24] ref-filter: make populate_value global

2018-01-26 Thread Olga Telezhnaya
Make function global for further using in cat-file.
In the end of patch series this function becomes internal again,
so this is a part of middle step. cat-file would use more general
functions further.

Signed-off-by: Olga Telezhnaia 
Mentored-by: Christian Couder 
Mentored by: Jeff King 
---
 ref-filter.c | 2 +-
 ref-filter.h | 3 +++
 2 files changed, 4 insertions(+), 1 deletion(-)

diff --git a/ref-filter.c b/ref-filter.c
index 95c85009f1f58..e69dd1ff5091f 100644
--- a/ref-filter.c
+++ b/ref-filter.c
@@ -1454,7 +1454,7 @@ static void need_object(struct ref_array_item *ref) {
 /*
  * Parse the object referred by ref, and grab needed value.
  */
-static int populate_value(struct ref_array_item *ref)
+int populate_value(struct ref_array_item *ref)
 {
int i;
 
diff --git a/ref-filter.h b/ref-filter.h
index 7aaf82799ec2d..6373167aaacd7 100644
--- a/ref-filter.h
+++ b/ref-filter.h
@@ -176,4 +176,7 @@ void setup_ref_filter_porcelain_msg(void);
 void pretty_print_ref(const char *name, const unsigned char *sha1,
  const struct ref_format *format);
 
+/* Fill the values of request and prepare all data for final string creation */
+int populate_value(struct ref_array_item *ref);
+
 #endif /*  REF_FILTER_H  */

--
https://github.com/git/git/pull/452


[PATCH RFC 23/24] cat-file: tests for new atoms added

2018-01-26 Thread Olga Telezhnaya
Add some tests for new formatting atoms from ref-filter.
Some of new atoms are supported automatically,
some of them are expanded into empty string
(because they are useless for some types of objects),
some of them could be supported later in other patches.

Signed-off-by: Olga Telezhnaia 
Mentored-by: Christian Couder 
Mentored by: Jeff King 
---
 t/t1006-cat-file.sh | 48 
 1 file changed, 48 insertions(+)

diff --git a/t/t1006-cat-file.sh b/t/t1006-cat-file.sh
index b19f332694620..e72fcaf0e02c5 100755
--- a/t/t1006-cat-file.sh
+++ b/t/t1006-cat-file.sh
@@ -20,6 +20,19 @@ maybe_remove_timestamp () {
 fi
 }
 
+test_atom () {
+name=$1
+sha1=$2
+atoms=$3
+expected=$4
+
+test_expect_success "$name" '
+   echo "$expected" >expect &&
+   echo $sha1 | git cat-file --batch-check="$atoms" >actual &&
+   test_cmp expect actual
+'
+}
+
 run_tests () {
 type=$1
 sha1=$2
@@ -119,6 +132,13 @@ $content"
maybe_remove_timestamp "$(cat actual.full)" $no_ts >actual &&
test_cmp expect actual
 '
+
+for atom in refname parent body trailers upstream push symref flag
+do
+   test_atom "Check %($atom) gives empty output" "$sha1" "%($atom)" ""
+done
+
+test_atom "Check %(HEAD) gives only one space as output" "$sha1" '%(HEAD)' 
' '
 }
 
 hello_content="Hello World"
@@ -140,6 +160,12 @@ test_expect_success '--batch-check without %(rest) 
considers whole line' '
test_cmp expect actual
 '
 
+shortname=`echo $hello_sha1 | sed 's/^.\{0\}\(.\{7\}\).*/\1/'`
+test_atom 'Check format option %(objectname:short) works' "$hello_sha1" 
'%(objectname:short)' "$shortname"
+
+test_atom 'Check format option %(align) is not broken' \
+"$hello_sha1" "%(align:8)%(objecttype)%(end)%(objectname)" "blob
$hello_sha1"
+
 tree_sha1=$(git write-tree)
 tree_size=33
 tree_pretty_content="100644 blob $hello_sha1   hello"
@@ -157,6 +183,17 @@ $commit_message"
 
 run_tests 'commit' $commit_sha1 $commit_size "$commit_content" 
"$commit_content" 1
 
+test_atom "Check format option %(if) is not broken" "$commit_sha1" \
+"%(if)%(author)%(then)%(objectname)%(end)" "$commit_sha1"
+test_atom "Check %(tree) works for commit" "$commit_sha1" "%(tree)" 
"$tree_sha1"
+test_atom "Check %(numparent) works for commit" "$commit_sha1" "%(numparent)" 
"0"
+test_atom "Check %(authorname) works for commit" "$commit_sha1" 
"%(authorname)" "$GIT_AUTHOR_NAME"
+test_atom "Check %(authoremail) works for commit" "$commit_sha1" 
"%(authoremail)" "<$GIT_AUTHOR_EMAIL>"
+test_atom "Check %(committername) works for commit" "$commit_sha1" 
"%(committername)" "$GIT_COMMITTER_NAME"
+test_atom "Check %(committeremail) works for commit" "$commit_sha1" 
"%(committeremail)" "<$GIT_COMMITTER_EMAIL>"
+test_atom "Check %(subject) works for commit" "$commit_sha1" "%(subject)" 
"$commit_message"
+test_atom "Check %(contents) works for commit" "$commit_sha1" "%(contents)" 
"$commit_message"
+
 tag_header_without_timestamp="object $hello_sha1
 type blob
 tag hellotag
@@ -171,6 +208,17 @@ tag_size=$(strlen "$tag_content")
 
 run_tests 'tag' $tag_sha1 $tag_size "$tag_content" "$tag_content" 1
 
+test_atom "Check %(object) works for tag" "$tag_sha1" "%(object)" "$hello_sha1"
+test_atom "Check %(type) works for tag" "$tag_sha1" "%(type)" "blob"
+test_atom "Check %(tag) works for tag" "$tag_sha1" "%(tag)" "hellotag"
+test_atom "Check %(taggername) works for tag" "$tag_sha1" "%(taggername)" 
"$GIT_COMMITTER_NAME"
+test_atom "Check %(taggeremail) works for tag" "$tag_sha1" "%(taggeremail)" 
"<$GIT_COMMITTER_EMAIL>"
+test_atom "Check %(subject) works for tag" "$tag_sha1" "%(subject)" 
"$tag_description"
+test_atom "Check %(contents) works for tag" "$tag_sha1" "%(contents)" 
"$tag_description"
+
+test_atom "Check %(color) gives no additional output" "$sha1" \
+"%(objectname) %(color:green) %(objecttype)" "$sha1  $type"
+
 test_expect_success \
 "Reach a blob from a tag pointing to it" \
 "test '$hello_content' = \"\$(git cat-file blob $tag_sha1)\""

--
https://github.com/git/git/pull/452


[PATCH RFC 17/24] cat-file: reuse printing logic from ref-filter

2018-01-26 Thread Olga Telezhnaya
Reuse code from ref-filter to print resulting message.

Signed-off-by: Olga Telezhnaia 
Mentored-by: Christian Couder 
Mentored by: Jeff King 
---
 builtin/cat-file.c | 52 +---
 ref-filter.c   | 30 +++---
 2 files changed, 32 insertions(+), 50 deletions(-)

diff --git a/builtin/cat-file.c b/builtin/cat-file.c
index bd803856537b8..26b35bef4ba02 100644
--- a/builtin/cat-file.c
+++ b/builtin/cat-file.c
@@ -176,45 +176,6 @@ static int cat_one_file(int opt, const char *exp_type, 
const char *obj_name,
return 0;
 }
 
-static int is_atom(const char *atom, const char *s, int slen)
-{
-   int alen = strlen(atom);
-   return alen == slen && !memcmp(atom, s, alen);
-}
-
-static void expand_atom(struct strbuf *sb, const char *atom, int len,
-struct ref_array_item *item)
-{
-   if (is_atom("objectname", atom, len))
-   strbuf_addstr(sb, oid_to_hex(>objectname));
-   else if (is_atom("objecttype", atom, len))
-   strbuf_addstr(sb, typename(item->type));
-   else if (is_atom("objectsize", atom, len))
-   strbuf_addf(sb, "%lu", item->size);
-   else if (is_atom("objectsize:disk", atom, len))
-   strbuf_addf(sb, "%"PRIuMAX, (uintmax_t)item->disk_size);
-   else if (is_atom("rest", atom, len)) {
-   if (item->rest)
-   strbuf_addstr(sb, item->rest);
-   } else if (is_atom("deltabase", atom, len))
-   strbuf_addstr(sb, oid_to_hex(item->delta_base_oid));
-}
-
-static size_t expand_format(struct strbuf *sb, const char *start, void *data)
-{
-   const char *end;
-   struct ref_array_item *item = data;
-
-   if (*start != '(')
-   return 0;
-   end = strchr(start + 1, ')');
-   if (!end)
-   die("format element '%s' does not end in ')'", start);
-
-   expand_atom(sb, start + 1, end - start - 1, item);
-   return end - start + 1;
-}
-
 static void batch_write(struct batch_options *opt, const void *data, int len)
 {
if (opt->buffer_output) {
@@ -282,22 +243,19 @@ static void print_object_or_die(struct batch_options 
*opt, struct expand_data *d
 static void batch_object_write(const char *obj_name, struct batch_options *opt,
   struct expand_data *data)
 {
-   struct strbuf buf = STRBUF_INIT;
struct ref_array_item item = {0};
 
item.objectname = data->oid;
item.rest = data->rest;
item.start_of_request = obj_name;
 
-   if (populate_value()) return;
-   data->type = item.type;
-
-   strbuf_expand(, opt->format.format, expand_format, );
-   strbuf_addch(, '\n');
-   batch_write(opt, buf.buf, buf.len);
-   strbuf_release();
+   if (show_ref_array_item(, >format))
+   return;
+   if (!opt->buffer_output)
+   fflush(stdout);
 
if (opt->print_contents) {
+   data->type = item.type;
print_object_or_die(opt, data);
batch_write(opt, "\n", 1);
}
diff --git a/ref-filter.c b/ref-filter.c
index 906a5344949f7..bfbc7c83fdd47 100644
--- a/ref-filter.c
+++ b/ref-filter.c
@@ -1522,7 +1522,21 @@ int populate_value(struct ref_array_item *ref)
name++;
}
 
-   if (starts_with(name, "refname"))
+   if (is_cat) {
+   if (starts_with(name, "objectname"))
+   v->s = oid_to_hex(>objectname);
+   else if (starts_with(name, "objecttype"))
+   v->s = typename(ref->type);
+   else if (starts_with(name, "objectsize")) {
+   v->s = xstrfmt("%lu", ref->size);
+   } else if (starts_with(name, "objectsize:disk")) {
+   v->s = xstrfmt("%"PRIuMAX, 
(uintmax_t)ref->disk_size);
+   } else if (starts_with(name, "rest"))
+   v->s = ref->rest;
+   else if (starts_with(name, "deltabase"))
+   v->s = xstrdup(oid_to_hex(ref->delta_base_oid));
+   continue;
+   } else if (starts_with(name, "refname"))
refname = get_refname(atom, ref);
else if (starts_with(name, "symref"))
refname = get_symref(atom, ref);
@@ -2219,6 +2233,7 @@ int format_ref_array_item(struct ref_array_item *info,
 {
const char *cp, *sp, *ep;
struct ref_formatting_state state = REF_FORMATTING_STATE_INIT;
+   int retval = 0;
 
state.quote_style = format->quote_style;
push_stack_element();
@@ -2229,13 +2244,22 @@ int format_ref_array_item(struct ref_array_item *info,
ep = strchr(sp, ')');
 

[PATCH RFC 22/24] for-each-ref: tests for new atoms added

2018-01-26 Thread Olga Telezhnaya
Add tests for new formatting atoms: rest, deltabase, objectsize:disk.
rest means nothing and we expand it into empty string.
We need this atom for cat-file command.
Have plans to support deltabase and objectsize:disk further
(as it is done in cat-file), now also expand it to empty string.

Signed-off-by: Olga Telezhnaia 
Mentored-by: Christian Couder 
Mentored by: Jeff King 
---
 t/t6300-for-each-ref.sh | 18 ++
 1 file changed, 18 insertions(+)

diff --git a/t/t6300-for-each-ref.sh b/t/t6300-for-each-ref.sh
index c128dfc579079..eee656a6abba9 100755
--- a/t/t6300-for-each-ref.sh
+++ b/t/t6300-for-each-ref.sh
@@ -316,6 +316,24 @@ test_expect_success 'exercise strftime with odd fields' '
test_cmp expected actual
 '
 
+test_expect_success 'Check format %(objectsize:disk) gives empty output ' '
+   echo >expected &&
+   git for-each-ref --format="%(objectsize:disk)" refs/heads >actual &&
+   test_cmp expected actual
+'
+
+test_expect_success 'Check format %(rest) gives empty output ' '
+   echo >expected &&
+   git for-each-ref --format="%(rest)" refs/heads >actual &&
+   test_cmp expected actual
+'
+
+test_expect_success 'Check format %(deltabase) gives empty output ' '
+   echo >expected &&
+   git for-each-ref --format="%(deltabase)" refs/heads >actual &&
+   test_cmp expected actual
+'
+
 cat >expected <<\EOF
 refs/heads/master
 refs/remotes/origin/master

--
https://github.com/git/git/pull/452


[PATCH RFC 12/24] ref-filter: get rid of expand_atom_into_fields

2018-01-26 Thread Olga Telezhnaya
Remove expand_atom_into_fields function and create same logic
in terms of ref-filter style.

Signed-off-by: Olga Telezhnaia 
Mentored-by: Christian Couder 
Mentored by: Jeff King 
---
 ref-filter.c | 45 +
 1 file changed, 21 insertions(+), 24 deletions(-)

diff --git a/ref-filter.c b/ref-filter.c
index 12ca236815411..8d10d356609e7 100644
--- a/ref-filter.c
+++ b/ref-filter.c
@@ -255,13 +255,29 @@ static void objectname_atom_parser(const struct 
ref_format *format, struct used_
 static void objectsize_atom_parser(const struct ref_format *format, struct 
used_atom *atom, const char *arg)
 {
if (!arg)
-   ; /* default to normal object size */
+   cat_file_info->info.sizep = _file_info->size;
else if (!strcmp(arg, "disk"))
cat_file_info->info.disk_sizep = _file_info->disk_size;
else
die(_("urecognized %%(objectsize) argument: %s"), arg);
 }
 
+static void objecttype_atom_parser(const struct ref_format *format, struct 
used_atom *atom, const char *arg)
+{
+   if (!arg)
+   cat_file_info->info.typep = _file_info->type;
+   else
+   die(_("urecognized %%(objecttype) argument: %s"), arg);
+}
+
+static void deltabase_atom_parser(const struct ref_format *format, struct 
used_atom *atom, const char *arg)
+{
+   if (!arg)
+   cat_file_info->info.delta_base_sha1 = 
cat_file_info->delta_base_oid.hash;
+   else
+   die(_("urecognized %%(deltabase) argument: %s"), arg);
+}
+
 static void refname_atom_parser(const struct ref_format *format, struct 
used_atom *atom, const char *arg)
 {
refname_atom_parser_internal(>u.refname, arg, atom->name);
@@ -384,10 +400,10 @@ static struct valid_atom {
 
 static struct valid_atom valid_cat_file_atom[] = {
{ "objectname" },
-   { "objecttype" },
+   { "objecttype", FIELD_STR, objecttype_atom_parser },
{ "objectsize", FIELD_ULONG, objectsize_atom_parser },
{ "rest" },
-   { "deltabase" },
+   { "deltabase", FIELD_STR, deltabase_atom_parser },
 };
 
 #define REF_FORMATTING_STATE_INIT  { 0, NULL }
@@ -411,25 +427,6 @@ struct atom_value {
struct used_atom *atom;
 };
 
-static int is_atom(const char *atom, const char *s, int slen)
-{
-   int alen = strlen(atom);
-   return alen == slen && !memcmp(atom, s, alen);
-}
-
-static void expand_atom_into_fields(const char *atom, int len,
-   struct expand_data *data)
-{
-   if (is_atom("objecttype", atom, len))
-   data->info.typep = >type;
-   else if (is_atom("objectsize", atom, len))
-   data->info.sizep = >size;
-   else if (is_atom("rest", atom, len))
-   data->split_on_whitespace = 1;
-   else if (is_atom("deltabase", atom, len))
-   data->info.delta_base_sha1 = data->delta_base_oid.hash;
-}
-
 /*
  * Used to parse format string and sort specifiers
  */
@@ -496,8 +493,8 @@ static int parse_ref_filter_atom(const struct ref_format 
*format,
need_tagged = 1;
if (!strcmp(valid_atom[i].name, "symref"))
need_symref = 1;
-   if (cat_file_info)
-   expand_atom_into_fields(atom, atom_len, cat_file_info);
+   if (cat_file_info && !strcmp(valid_atom[i].name, "rest"))
+   cat_file_info->split_on_whitespace = 1;
return at;
 }
 

--
https://github.com/git/git/pull/452


[PATCH RFC 05/24] ref-filter: make valid_atom as function parameter

2018-01-26 Thread Olga Telezhnaya
Make valid_atom as a function parameter,
there could be another variable further.
Need that for further reusing of formatting logic in cat-file.c.

We do not need to allow users to pass their own valid_atom variable in
global functions like verify_ref_format because in the end we want to
have same set of valid atoms for all commands. But, as a first step
of migrating, I create further another version of valid_atom
for cat-file.

Signed-off-by: Olga Telezhnaia 
Mentored-by: Christian Couder 
Mentored by: Jeff King 
---
 ref-filter.c | 17 +++--
 1 file changed, 11 insertions(+), 6 deletions(-)

diff --git a/ref-filter.c b/ref-filter.c
index 7030d35c84a81..ee2aa7d6d072b 100644
--- a/ref-filter.c
+++ b/ref-filter.c
@@ -325,7 +325,7 @@ static void head_atom_parser(const struct ref_format 
*format, struct used_atom *
atom->u.head = resolve_refdup("HEAD", RESOLVE_REF_READING, NULL, NULL);
 }
 
-static struct {
+static struct valid_atom {
const char *name;
cmp_type cmp_type;
void (*parser)(const struct ref_format *format, struct used_atom *atom, 
const char *arg);
@@ -396,6 +396,7 @@ struct atom_value {
  * Used to parse format string and sort specifiers
  */
 static int parse_ref_filter_atom(const struct ref_format *format,
+const struct valid_atom *valid_atom, int 
n_atoms,
 const char *atom, const char *ep)
 {
const char *sp;
@@ -425,13 +426,13 @@ static int parse_ref_filter_atom(const struct ref_format 
*format,
atom_len = (arg ? arg : ep) - sp;
 
/* Is the atom a valid one? */
-   for (i = 0; i < ARRAY_SIZE(valid_atom); i++) {
+   for (i = 0; i < n_atoms; i++) {
int len = strlen(valid_atom[i].name);
if (len == atom_len && !memcmp(valid_atom[i].name, sp, len))
break;
}
 
-   if (ARRAY_SIZE(valid_atom) <= i)
+   if (n_atoms <= i)
die(_("unknown field name: %.*s"), (int)(ep-atom), atom);
 
/* Add it in, including the deref prefix */
@@ -708,7 +709,8 @@ int verify_ref_format(struct ref_format *format)
if (!ep)
return error(_("malformed format string %s"), sp);
/* sp points at "%(" and ep points at the closing ")" */
-   at = parse_ref_filter_atom(format, sp + 2, ep);
+   at = parse_ref_filter_atom(format, valid_atom,
+  ARRAY_SIZE(valid_atom), sp + 2, ep);
cp = ep + 1;
 
if (skip_prefix(used_atom[at].name, "color:", ))
@@ -2143,7 +2145,9 @@ int format_ref_array_item(struct ref_array_item *info,
if (cp < sp)
append_literal(cp, sp, );
get_ref_atom_value(info,
-  parse_ref_filter_atom(format, sp + 2, ep),
+  parse_ref_filter_atom(format, valid_atom,
+ARRAY_SIZE(valid_atom),
+sp + 2, ep),
   );
atomv->handler(atomv, );
}
@@ -2194,7 +2198,8 @@ static int parse_sorting_atom(const char *atom)
 */
struct ref_format dummy = REF_FORMAT_INIT;
const char *end = atom + strlen(atom);
-   return parse_ref_filter_atom(, atom, end);
+   return parse_ref_filter_atom(, valid_atom,
+ARRAY_SIZE(valid_atom), atom, end);
 }
 
 /*  If no sorting option is given, use refname to sort as default */

--
https://github.com/git/git/pull/452


[PATCH RFC 06/24] cat-file: move struct expand_data into ref-filter

2018-01-26 Thread Olga Telezhnaya
Need that for further reusing of formatting logic in cat-file.
Have plans to get rid of using expand_data in cat-file at all,
and use it only in ref-filter for collecting, formatting and printing
needed data.

Signed-off-by: Olga Telezhnaia 
Mentored-by: Christian Couder 
Mentored by: Jeff King 
---
 builtin/cat-file.c | 36 
 ref-filter.h   | 36 
 2 files changed, 36 insertions(+), 36 deletions(-)

diff --git a/builtin/cat-file.c b/builtin/cat-file.c
index 65c300184cab8..490d9f8a8a922 100644
--- a/builtin/cat-file.c
+++ b/builtin/cat-file.c
@@ -176,42 +176,6 @@ static int cat_one_file(int opt, const char *exp_type, 
const char *obj_name,
return 0;
 }
 
-struct expand_data {
-   struct object_id oid;
-   enum object_type type;
-   unsigned long size;
-   off_t disk_size;
-   const char *rest;
-   struct object_id delta_base_oid;
-
-   /*
-* If mark_query is true, we do not expand anything, but rather
-* just mark the object_info with items we wish to query.
-*/
-   int mark_query;
-
-   /*
-* Whether to split the input on whitespace before feeding it to
-* get_sha1; this is decided during the mark_query phase based on
-* whether we have a %(rest) token in our format.
-*/
-   int split_on_whitespace;
-
-   /*
-* After a mark_query run, this object_info is set up to be
-* passed to sha1_object_info_extended. It will point to the data
-* elements above, so you can retrieve the response from there.
-*/
-   struct object_info info;
-
-   /*
-* This flag will be true if the requested batch format and options
-* don't require us to call sha1_object_info, which can then be
-* optimized out.
-*/
-   unsigned skip_object_info : 1;
-};
-
 static int is_atom(const char *atom, const char *s, int slen)
 {
int alen = strlen(atom);
diff --git a/ref-filter.h b/ref-filter.h
index ff416b733b4b1..56093a85d52b8 100644
--- a/ref-filter.h
+++ b/ref-filter.h
@@ -72,6 +72,42 @@ struct ref_filter {
verbose;
 };
 
+struct expand_data {
+   struct object_id oid;
+   enum object_type type;
+   unsigned long size;
+   off_t disk_size;
+   const char *rest;
+   struct object_id delta_base_oid;
+
+   /*
+* If mark_query is true, we do not expand anything, but rather
+* just mark the object_info with items we wish to query.
+*/
+   int mark_query;
+
+   /*
+* Whether to split the input on whitespace before feeding it to
+* get_sha1; this is decided during the mark_query phase based on
+* whether we have a %(rest) token in our format.
+*/
+   int split_on_whitespace;
+
+   /*
+* After a mark_query run, this object_info is set up to be
+* passed to sha1_object_info_extended. It will point to the data
+* elements above, so you can retrieve the response from there.
+*/
+   struct object_info info;
+
+   /*
+* This flag will be true if the requested batch format and options
+* don't require us to call sha1_object_info, which can then be
+* optimized out.
+*/
+   unsigned skip_object_info : 1;
+};
+
 struct ref_format {
/*
 * Set these to define the format; make sure you call

--
https://github.com/git/git/pull/452


[PATCH RFC 07/24] cat-file: start migrating to ref-filter

2018-01-26 Thread Olga Telezhnaya
Start moving formatting stuff related to data preparation
from cat-file to ref-filter.
Start from simple moving, it would be integrated into
all ref-filter processes further.

Signed-off-by: Olga Telezhnaia 
Mentored-by: Christian Couder 
Mentored by: Jeff King 
---
 builtin/cat-file.c | 32 +++-
 ref-filter.c   | 41 -
 ref-filter.h   | 12 ++--
 3 files changed, 45 insertions(+), 40 deletions(-)

diff --git a/builtin/cat-file.c b/builtin/cat-file.c
index 490d9f8a8a922..909412747cbd2 100644
--- a/builtin/cat-file.c
+++ b/builtin/cat-file.c
@@ -182,25 +182,6 @@ static int is_atom(const char *atom, const char *s, int 
slen)
return alen == slen && !memcmp(atom, s, alen);
 }
 
-static void expand_atom_into_fields(struct strbuf *sb, const char *atom, int 
len,
-   struct expand_data *data)
-{
-   if (is_atom("objectname", atom, len))
-   ; /* do nothing */
-   else if (is_atom("objecttype", atom, len))
-   data->info.typep = >type;
-   else if (is_atom("objectsize", atom, len))
-   data->info.sizep = >size;
-   else if (is_atom("objectsize:disk", atom, len))
-   data->info.disk_sizep = >disk_size;
-   else if (is_atom("rest", atom, len))
-   data->split_on_whitespace = 1;
-   else if (is_atom("deltabase", atom, len))
-   data->info.delta_base_sha1 = data->delta_base_oid.hash;
-   else
-   die("unknown format element: %.*s", len, atom);
-}
-
 static void expand_atom(struct strbuf *sb, const char *atom, int len,
 struct expand_data *data)
 {
@@ -217,8 +198,6 @@ static void expand_atom(struct strbuf *sb, const char 
*atom, int len,
strbuf_addstr(sb, data->rest);
} else if (is_atom("deltabase", atom, len))
strbuf_addstr(sb, oid_to_hex(>delta_base_oid));
-   else
-   die("unknown format element: %.*s", len, atom);
 }
 
 static size_t expand_format(struct strbuf *sb, const char *start, void *vdata)
@@ -232,11 +211,7 @@ static size_t expand_format(struct strbuf *sb, const char 
*start, void *vdata)
if (!end)
die("format element '%s' does not end in ')'", start);
 
-   if (data->mark_query)
-   expand_atom_into_fields(sb, start + 1, end - start - 1, data);
-   else
-   expand_atom(sb, start + 1, end - start - 1, data);
-
+   expand_atom(sb, start + 1, end - start - 1, data);
return end - start + 1;
 }
 
@@ -420,9 +395,8 @@ static int batch_objects(struct batch_options *opt)
 * object.
 */
memset(, 0, sizeof(data));
-   data.mark_query = 1;
-   strbuf_expand(, opt->format.format, expand_format, );
-   data.mark_query = 0;
+   opt->format.cat_file_data = 
+   verify_ref_format(>format);
if (opt->cmdmode)
data.split_on_whitespace = 1;
 
diff --git a/ref-filter.c b/ref-filter.c
index ee2aa7d6d072b..8e384b2818b22 100644
--- a/ref-filter.c
+++ b/ref-filter.c
@@ -392,6 +392,31 @@ struct atom_value {
struct used_atom *atom;
 };
 
+static int is_atom(const char *atom, const char *s, int slen)
+{
+   int alen = strlen(atom);
+   return alen == slen && !memcmp(atom, s, alen);
+}
+
+static void expand_atom_into_fields(const char *atom, int len,
+   struct expand_data *data)
+{
+   if (is_atom("objectname", atom, len))
+   ; /* do nothing */
+   else if (is_atom("objecttype", atom, len))
+   data->info.typep = >type;
+   else if (is_atom("objectsize", atom, len))
+   data->info.sizep = >size;
+   else if (is_atom("objectsize:disk", atom, len))
+   data->info.disk_sizep = >disk_size;
+   else if (is_atom("rest", atom, len))
+   data->split_on_whitespace = 1;
+   else if (is_atom("deltabase", atom, len))
+   data->info.delta_base_sha1 = data->delta_base_oid.hash;
+   else
+   die("unknown format element: %.*s", len, atom);
+}
+
 /*
  * Used to parse format string and sort specifiers
  */
@@ -709,12 +734,18 @@ int verify_ref_format(struct ref_format *format)
if (!ep)
return error(_("malformed format string %s"), sp);
/* sp points at "%(" and ep points at the closing ")" */
-   at = parse_ref_filter_atom(format, valid_atom,
-  ARRAY_SIZE(valid_atom), sp + 2, ep);
-   cp = ep + 1;
 
-   if (skip_prefix(used_atom[at].name, "color:", ))
-   format->need_color_reset_at_eol = !!strcmp(color, 
"reset");
+   if (format->cat_file_data)
+   expand_atom_into_fields(sp + 2, ep - sp - 2,
+

[PATCH RFC 21/24] ref-filter: work with objectsize:disk

2018-01-26 Thread Olga Telezhnaya
Make a temporary solution for commands that could use
objectsize:disk atom.
It's better to fill it with value or give an error if there is no value
for this atom, but as a first solution we do dothing.
It means that if objectsize:disk is used, we put an empty string there.

Signed-off-by: Olga Telezhnaia 
Mentored-by: Christian Couder 
Mentored by: Jeff King 
---
 ref-filter.c | 6 --
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/ref-filter.c b/ref-filter.c
index 2cac394e93f52..bf49ed21eaac5 100644
--- a/ref-filter.c
+++ b/ref-filter.c
@@ -826,8 +826,10 @@ static void grab_common_values(struct atom_value *val, int 
deref, struct object
v->value = sz;
v->s = xstrfmt("%lu", sz);
} else if (!strcmp(name, "objectsize:disk")) {
-   v->value = cat_file_info.disk_size;
-   v->s = xstrfmt("%"PRIuMAX, (uintmax_t)v->value);
+   if (is_cat) {
+   v->value = cat_file_info.disk_size;
+   v->s = xstrfmt("%"PRIuMAX, (uintmax_t)v->value);
+   }
} else if (deref)
grab_objectname(name, obj->oid.hash, v, _atom[i]);
}

--
https://github.com/git/git/pull/452


[PATCH RFC 11/24] cat-file: start reusing populate_value

2018-01-26 Thread Olga Telezhnaya
Move logic related to getting object info from cat-file to ref-filter.
It will help to reuse whole formatting logic from ref-filter further.

Signed-off-by: Olga Telezhnaia 
Mentored-by: Christian Couder 
Mentored by: Jeff King 
---
 builtin/cat-file.c | 16 +++-
 ref-filter.c   | 20 
 ref-filter.h   |  2 ++
 3 files changed, 25 insertions(+), 13 deletions(-)

diff --git a/builtin/cat-file.c b/builtin/cat-file.c
index 61b7acc79155d..c2ca645662ae7 100644
--- a/builtin/cat-file.c
+++ b/builtin/cat-file.c
@@ -285,21 +285,11 @@ static void batch_object_write(const char *obj_name, 
struct batch_options *opt,
struct strbuf buf = STRBUF_INIT;
struct ref_array_item item = {0};
 
-   if (!data->skip_object_info &&
-   sha1_object_info_extended(data->oid.hash, >info,
- OBJECT_INFO_LOOKUP_REPLACE) < 0) {
-   printf("%s missing\n",
-  obj_name ? obj_name : oid_to_hex(>oid));
-   fflush(stdout);
-   return;
-   }
-
item.objectname = data->oid;
-   item.type = data->type;
-   item.size = data->size;
-   item.disk_size = data->disk_size;
item.rest = data->rest;
-   item.delta_base_oid = >delta_base_oid;
+   item.start_of_request = obj_name;
+
+   if (populate_value()) return;
 
strbuf_expand(, opt->format.format, expand_format, );
strbuf_addch(, '\n');
diff --git a/ref-filter.c b/ref-filter.c
index e69dd1ff5091f..12ca236815411 100644
--- a/ref-filter.c
+++ b/ref-filter.c
@@ -1451,6 +1451,23 @@ static void need_object(struct ref_array_item *ref) {
free(buf);
 }
 
+static int check_and_fill_for_cat(struct ref_array_item *ref)
+{
+   if (!cat_file_info->skip_object_info &&
+   sha1_object_info_extended(ref->objectname.hash, 
_file_info->info,
+ OBJECT_INFO_LOOKUP_REPLACE) < 0) {
+   const char *e = ref->start_of_request;
+   printf("%s missing\n", e ? e : oid_to_hex(>objectname));
+   fflush(stdout);
+   return -1;
+   }
+   ref->type = cat_file_info->type;
+   ref->size = cat_file_info->size;
+   ref->disk_size = cat_file_info->disk_size;
+   ref->delta_base_oid = _file_info->delta_base_oid;
+   return 0;
+}
+
 /*
  * Parse the object referred by ref, and grab needed value.
  */
@@ -1467,6 +1484,9 @@ int populate_value(struct ref_array_item *ref)
ref->symref = "";
}
 
+   if (cat_file_info && check_and_fill_for_cat(ref))
+   return -1;
+
/* Fill in specials first */
for (i = 0; i < used_atom_cnt; i++) {
struct used_atom *atom = _atom[i];
diff --git a/ref-filter.h b/ref-filter.h
index 6373167aaacd7..e41d2913c0fff 100644
--- a/ref-filter.h
+++ b/ref-filter.h
@@ -45,6 +45,8 @@ struct ref_array_item {
off_t disk_size;
const char *rest;
struct object_id *delta_base_oid;
+   /* Need it for better explanation in error log. */
+   const char *start_of_request;
char refname[FLEX_ARRAY];
 };
 

--
https://github.com/git/git/pull/452


[PATCH RFC 09/24] cat-file: start use ref_array_item struct

2018-01-26 Thread Olga Telezhnaya
Moving from using expand_data to ref_array_item structure.
That helps us to reuse functions from ref-filter easier.

Signed-off-by: Olga Telezhnaia 
Mentored-by: Christian Couder 
Mentored by: Jeff King 
---
 builtin/cat-file.c | 32 
 ref-filter.h   |  5 +
 2 files changed, 25 insertions(+), 12 deletions(-)

diff --git a/builtin/cat-file.c b/builtin/cat-file.c
index 909412747cbd2..61b7acc79155d 100644
--- a/builtin/cat-file.c
+++ b/builtin/cat-file.c
@@ -183,27 +183,27 @@ static int is_atom(const char *atom, const char *s, int 
slen)
 }
 
 static void expand_atom(struct strbuf *sb, const char *atom, int len,
-struct expand_data *data)
+struct ref_array_item *item)
 {
if (is_atom("objectname", atom, len))
-   strbuf_addstr(sb, oid_to_hex(>oid));
+   strbuf_addstr(sb, oid_to_hex(>objectname));
else if (is_atom("objecttype", atom, len))
-   strbuf_addstr(sb, typename(data->type));
+   strbuf_addstr(sb, typename(item->type));
else if (is_atom("objectsize", atom, len))
-   strbuf_addf(sb, "%lu", data->size);
+   strbuf_addf(sb, "%lu", item->size);
else if (is_atom("objectsize:disk", atom, len))
-   strbuf_addf(sb, "%"PRIuMAX, (uintmax_t)data->disk_size);
+   strbuf_addf(sb, "%"PRIuMAX, (uintmax_t)item->disk_size);
else if (is_atom("rest", atom, len)) {
-   if (data->rest)
-   strbuf_addstr(sb, data->rest);
+   if (item->rest)
+   strbuf_addstr(sb, item->rest);
} else if (is_atom("deltabase", atom, len))
-   strbuf_addstr(sb, oid_to_hex(>delta_base_oid));
+   strbuf_addstr(sb, oid_to_hex(item->delta_base_oid));
 }
 
-static size_t expand_format(struct strbuf *sb, const char *start, void *vdata)
+static size_t expand_format(struct strbuf *sb, const char *start, void *data)
 {
const char *end;
-   struct expand_data *data = vdata;
+   struct ref_array_item *item = data;
 
if (*start != '(')
return 0;
@@ -211,7 +211,7 @@ static size_t expand_format(struct strbuf *sb, const char 
*start, void *vdata)
if (!end)
die("format element '%s' does not end in ')'", start);
 
-   expand_atom(sb, start + 1, end - start - 1, data);
+   expand_atom(sb, start + 1, end - start - 1, item);
return end - start + 1;
 }
 
@@ -283,6 +283,7 @@ static void batch_object_write(const char *obj_name, struct 
batch_options *opt,
   struct expand_data *data)
 {
struct strbuf buf = STRBUF_INIT;
+   struct ref_array_item item = {0};
 
if (!data->skip_object_info &&
sha1_object_info_extended(data->oid.hash, >info,
@@ -293,7 +294,14 @@ static void batch_object_write(const char *obj_name, 
struct batch_options *opt,
return;
}
 
-   strbuf_expand(, opt->format.format, expand_format, data);
+   item.objectname = data->oid;
+   item.type = data->type;
+   item.size = data->size;
+   item.disk_size = data->disk_size;
+   item.rest = data->rest;
+   item.delta_base_oid = >delta_base_oid;
+
+   strbuf_expand(, opt->format.format, expand_format, );
strbuf_addch(, '\n');
batch_write(opt, buf.buf, buf.len);
strbuf_release();
diff --git a/ref-filter.h b/ref-filter.h
index b50c8e6aaf2c4..7aaf82799ec2d 100644
--- a/ref-filter.h
+++ b/ref-filter.h
@@ -40,6 +40,11 @@ struct ref_array_item {
const char *symref;
struct commit *commit;
struct atom_value *value;
+   enum object_type type;
+   unsigned long size;
+   off_t disk_size;
+   const char *rest;
+   struct object_id *delta_base_oid;
char refname[FLEX_ARRAY];
 };
 

--
https://github.com/git/git/pull/452


[PATCH RFC 04/24] cat-file: reuse struct ref_format

2018-01-26 Thread Olga Telezhnaya
Start using ref_format struct instead of simple char*.
Need that for further reusing of formatting logic from ref-filter.

Signed-off-by: Olga Telezhnaia 
Mentored-by: Christian Couder 
Mentored by: Jeff King 
---
 builtin/cat-file.c | 15 ---
 1 file changed, 8 insertions(+), 7 deletions(-)

diff --git a/builtin/cat-file.c b/builtin/cat-file.c
index f783b39b9bd5c..65c300184cab8 100644
--- a/builtin/cat-file.c
+++ b/builtin/cat-file.c
@@ -13,15 +13,16 @@
 #include "tree-walk.h"
 #include "sha1-array.h"
 #include "packfile.h"
+#include "ref-filter.h"
 
 struct batch_options {
+   struct ref_format format;
int enabled;
int follow_symlinks;
int print_contents;
int buffer_output;
int all_objects;
int cmdmode; /* may be 'w' or 'c' for --filters or --textconv */
-   const char *format;
 };
 
 static const char *force_path;
@@ -353,7 +354,7 @@ static void batch_object_write(const char *obj_name, struct 
batch_options *opt,
return;
}
 
-   strbuf_expand(, opt->format, expand_format, data);
+   strbuf_expand(, opt->format.format, expand_format, data);
strbuf_addch(, '\n');
batch_write(opt, buf.buf, buf.len);
strbuf_release();
@@ -446,8 +447,8 @@ static int batch_objects(struct batch_options *opt)
int save_warning;
int retval = 0;
 
-   if (!opt->format)
-   opt->format = "%(objectname) %(objecttype) %(objectsize)";
+   if (!opt->format.format)
+   opt->format.format = "%(objectname) %(objecttype) 
%(objectsize)";
 
/*
 * Expand once with our special mark_query flag, which will prime the
@@ -456,7 +457,7 @@ static int batch_objects(struct batch_options *opt)
 */
memset(, 0, sizeof(data));
data.mark_query = 1;
-   strbuf_expand(, opt->format, expand_format, );
+   strbuf_expand(, opt->format.format, expand_format, );
data.mark_query = 0;
if (opt->cmdmode)
data.split_on_whitespace = 1;
@@ -548,7 +549,7 @@ static int batch_option_callback(const struct option *opt,
 
bo->enabled = 1;
bo->print_contents = !strcmp(opt->long_name, "batch");
-   bo->format = arg;
+   bo->format.format = arg;
 
return 0;
 }
@@ -557,7 +558,7 @@ int cmd_cat_file(int argc, const char **argv, const char 
*prefix)
 {
int opt = 0;
const char *exp_type = NULL, *obj_name = NULL;
-   struct batch_options batch = {0};
+   struct batch_options batch = { REF_FORMAT_INIT };
int unknown_type = 0;
 
const struct option options[] = {

--
https://github.com/git/git/pull/452


[PATCH RFC 24/24] cat-file: update of docs

2018-01-26 Thread Olga Telezhnaya
Update the docs for cat-file command. Some new formatting atoms added
because of reusing ref-filter code.
We do not support cat-file atoms in general formatting logic
(there is just the support for cat-file), that is why some of the atoms
are still explained in cat-file docs.
We need to move these explanations when atoms will be supported
by other commands.

Signed-off-by: Olga Telezhnaia 
Mentored-by: Christian Couder 
Mentored by: Jeff King 
---
 Documentation/git-cat-file.txt | 13 ++---
 1 file changed, 2 insertions(+), 11 deletions(-)

diff --git a/Documentation/git-cat-file.txt b/Documentation/git-cat-file.txt
index f90f09b03fae5..90639ac21d0e8 100644
--- a/Documentation/git-cat-file.txt
+++ b/Documentation/git-cat-file.txt
@@ -187,17 +187,8 @@ linkgit:git-rev-parse[1].
 You can specify the information shown for each object by using a custom
 ``. The `` is copied literally to stdout for each
 object, with placeholders of the form `%(atom)` expanded, followed by a
-newline. The available atoms are:
-
-`objectname`::
-   The 40-hex object name of the object.
-
-`objecttype`::
-   The type of the object (the same as `cat-file -t` reports).
-
-`objectsize`::
-   The size, in bytes, of the object (the same as `cat-file -s`
-   reports).
+newline. The available atoms are the same as that of
+linkgit:git-for-each-ref[1], but there are some additional ones:
 
 `objectsize:disk`::
The size, in bytes, that the object takes up on disk. See the

--
https://github.com/git/git/pull/452


[PATCH RFC 08/24] ref-filter: reuse parse_ref_filter_atom

2018-01-26 Thread Olga Telezhnaya
Continue migrating formatting logic from cat-file to ref-filter.
Reuse parse_ref_filter_atom for unifying all processes in ref-filter
and further reducing of expand_atom_into_fields function.

Signed-off-by: Olga Telezhnaia 
Mentored-by: Christian Couder 
Mentored by: Jeff King 
---
 ref-filter.c | 38 +++---
 1 file changed, 27 insertions(+), 11 deletions(-)

diff --git a/ref-filter.c b/ref-filter.c
index 8e384b2818b22..95c85009f1f58 100644
--- a/ref-filter.c
+++ b/ref-filter.c
@@ -100,6 +100,7 @@ static struct used_atom {
} u;
 } *used_atom;
 static int used_atom_cnt, need_tagged, need_symref;
+struct expand_data *cat_file_info;
 
 static void color_atom_parser(const struct ref_format *format, struct 
used_atom *atom, const char *color_value)
 {
@@ -251,6 +252,16 @@ static void objectname_atom_parser(const struct ref_format 
*format, struct used_
die(_("unrecognized %%(objectname) argument: %s"), arg);
 }
 
+static void objectsize_atom_parser(const struct ref_format *format, struct 
used_atom *atom, const char *arg)
+{
+   if (!arg)
+   ; /* default to normal object size */
+   else if (!strcmp(arg, "disk"))
+   cat_file_info->info.disk_sizep = _file_info->disk_size;
+   else
+   die(_("urecognized %%(objectsize) argument: %s"), arg);
+}
+
 static void refname_atom_parser(const struct ref_format *format, struct 
used_atom *atom, const char *arg)
 {
refname_atom_parser_internal(>u.refname, arg, atom->name);
@@ -371,6 +382,14 @@ static struct valid_atom {
{ "else" },
 };
 
+static struct valid_atom valid_cat_file_atom[] = {
+   { "objectname" },
+   { "objecttype" },
+   { "objectsize", FIELD_ULONG, objectsize_atom_parser },
+   { "rest" },
+   { "deltabase" },
+};
+
 #define REF_FORMATTING_STATE_INIT  { 0, NULL }
 
 struct ref_formatting_stack {
@@ -401,20 +420,14 @@ static int is_atom(const char *atom, const char *s, int 
slen)
 static void expand_atom_into_fields(const char *atom, int len,
struct expand_data *data)
 {
-   if (is_atom("objectname", atom, len))
-   ; /* do nothing */
-   else if (is_atom("objecttype", atom, len))
+   if (is_atom("objecttype", atom, len))
data->info.typep = >type;
else if (is_atom("objectsize", atom, len))
data->info.sizep = >size;
-   else if (is_atom("objectsize:disk", atom, len))
-   data->info.disk_sizep = >disk_size;
else if (is_atom("rest", atom, len))
data->split_on_whitespace = 1;
else if (is_atom("deltabase", atom, len))
data->info.delta_base_sha1 = data->delta_base_oid.hash;
-   else
-   die("unknown format element: %.*s", len, atom);
 }
 
 /*
@@ -483,6 +496,8 @@ static int parse_ref_filter_atom(const struct ref_format 
*format,
need_tagged = 1;
if (!strcmp(valid_atom[i].name, "symref"))
need_symref = 1;
+   if (cat_file_info)
+   expand_atom_into_fields(atom, atom_len, cat_file_info);
return at;
 }
 
@@ -726,6 +741,7 @@ int verify_ref_format(struct ref_format *format)
 {
const char *cp, *sp;
 
+   cat_file_info = format->cat_file_data;
format->need_color_reset_at_eol = 0;
for (cp = format->format; *cp && (sp = find_next(cp)); ) {
const char *color, *ep = strchr(sp, ')');
@@ -735,10 +751,10 @@ int verify_ref_format(struct ref_format *format)
return error(_("malformed format string %s"), sp);
/* sp points at "%(" and ep points at the closing ")" */
 
-   if (format->cat_file_data)
-   expand_atom_into_fields(sp + 2, ep - sp - 2,
-   format->cat_file_data);
-   else {
+   if (format->cat_file_data) {
+   at = parse_ref_filter_atom(format, valid_cat_file_atom,
+  
ARRAY_SIZE(valid_cat_file_atom), sp + 2, ep);
+   } else {
at = parse_ref_filter_atom(format, valid_atom,
   ARRAY_SIZE(valid_atom), sp + 
2, ep);
if (skip_prefix(used_atom[at].name, "color:", ))

--
https://github.com/git/git/pull/452


[PATCH RFC 15/24] cat-file: move skip_object_info into ref-filter

2018-01-26 Thread Olga Telezhnaya
Move logic related to skip_object_info into ref-filter,
so that cat-file does not use that field at all.

Signed-off-by: Olga Telezhnaia 
Mentored-by: Christian Couder 
Mentored by: Jeff King 
---
 builtin/cat-file.c | 7 +--
 ref-filter.c   | 5 +
 ref-filter.h   | 1 +
 3 files changed, 7 insertions(+), 6 deletions(-)

diff --git a/builtin/cat-file.c b/builtin/cat-file.c
index 601a87d9b5f7c..3a52c551f366a 100644
--- a/builtin/cat-file.c
+++ b/builtin/cat-file.c
@@ -394,14 +394,9 @@ static int batch_objects(struct batch_options *opt)
memset(, 0, sizeof(data));
opt->format.cat_file_data = 
opt->format.is_cat = 1;
+   opt->format.all_objects = opt->all_objects;
verify_ref_format(>format);
 
-   if (opt->all_objects) {
-   struct object_info empty = OBJECT_INFO_INIT;
-   if (!memcmp(, , sizeof(empty)))
-   data.skip_object_info = 1;
-   }
-
/*
 * If we are printing out the object, then always fill in the type,
 * since we will want to decide whether or not to stream.
diff --git a/ref-filter.c b/ref-filter.c
index 51da76dc21136..29a1b75c93181 100644
--- a/ref-filter.c
+++ b/ref-filter.c
@@ -777,6 +777,11 @@ int verify_ref_format(struct ref_format *format)
}
if (format->need_color_reset_at_eol && !want_color(format->use_color))
format->need_color_reset_at_eol = 0;
+   if (is_cat && format->all_objects) {
+   struct object_info empty = OBJECT_INFO_INIT;
+   if (!memcmp(_file_info->info, , sizeof(empty)))
+   cat_file_info->skip_object_info = 1;
+   }
return 0;
 }
 
diff --git a/ref-filter.h b/ref-filter.h
index 276de387f3bd0..4af89c4c86bee 100644
--- a/ref-filter.h
+++ b/ref-filter.h
@@ -120,6 +120,7 @@ struct ref_format {
 */
struct expand_data *cat_file_data;
int is_cat;
+   int all_objects;
 };
 
 #define REF_FORMAT_INIT { NULL, 0, -1 }

--
https://github.com/git/git/pull/452


[PATCH RFC 02/24] ref-filter: add return value to some functions

2018-01-26 Thread Olga Telezhnaya
Add return flag to format_ref_array_item, show_ref_array_item,
get_ref_array_info and populate_value for further using.
Need it to handle situations when item is broken but we can not invoke
die() because we are in batch mode and all items need to be processed.

Signed-off-by: Olga Telezhnaia 
Mentored-by: Christian Couder 
Mentored by: Jeff King 
---
 ref-filter.c | 21 +
 ref-filter.h |  4 ++--
 2 files changed, 15 insertions(+), 10 deletions(-)

diff --git a/ref-filter.c b/ref-filter.c
index 37337b57aacf4..7030d35c84a81 100644
--- a/ref-filter.c
+++ b/ref-filter.c
@@ -1405,7 +1405,7 @@ static void need_object(struct ref_array_item *ref) {
 /*
  * Parse the object referred by ref, and grab needed value.
  */
-static void populate_value(struct ref_array_item *ref)
+static int populate_value(struct ref_array_item *ref)
 {
int i;
 
@@ -1526,20 +1526,22 @@ static void populate_value(struct ref_array_item *ref)
break;
}
}
-   return;
+   return 0;
 }
 
 /*
  * Given a ref, return the value for the atom.  This lazily gets value
  * out of the object by calling populate value.
  */
-static void get_ref_atom_value(struct ref_array_item *ref, int atom, struct 
atom_value **v)
+static int get_ref_atom_value(struct ref_array_item *ref, int atom, struct 
atom_value **v)
 {
+   int retval = 0;
if (!ref->value) {
-   populate_value(ref);
+   retval = populate_value(ref);
fill_missing_values(ref->value);
}
*v = >value[atom];
+   return retval;
 }
 
 /*
@@ -2124,7 +2126,7 @@ static void append_literal(const char *cp, const char 
*ep, struct ref_formatting
}
 }
 
-void format_ref_array_item(struct ref_array_item *info,
+int format_ref_array_item(struct ref_array_item *info,
   const struct ref_format *format,
   struct strbuf *final_buf)
 {
@@ -2158,17 +2160,20 @@ void format_ref_array_item(struct ref_array_item *info,
die(_("format: %%(end) atom missing"));
strbuf_addbuf(final_buf, >output);
pop_stack_element();
+   return 0;
 }
 
-void show_ref_array_item(struct ref_array_item *info,
+int show_ref_array_item(struct ref_array_item *info,
 const struct ref_format *format)
 {
struct strbuf final_buf = STRBUF_INIT;
+   int retval = format_ref_array_item(info, format, _buf);
 
-   format_ref_array_item(info, format, _buf);
fwrite(final_buf.buf, 1, final_buf.len, stdout);
strbuf_release(_buf);
-   putchar('\n');
+   if (!retval)
+   putchar('\n');
+   return retval;
 }
 
 void pretty_print_ref(const char *name, const unsigned char *sha1,
diff --git a/ref-filter.h b/ref-filter.h
index 0d98342b34319..ff416b733b4b1 100644
--- a/ref-filter.h
+++ b/ref-filter.h
@@ -110,11 +110,11 @@ int verify_ref_format(struct ref_format *format);
 /*  Sort the given ref_array as per the ref_sorting provided */
 void ref_array_sort(struct ref_sorting *sort, struct ref_array *array);
 /*  Based on the given format and quote_style, fill the strbuf */
-void format_ref_array_item(struct ref_array_item *info,
+int format_ref_array_item(struct ref_array_item *info,
   const struct ref_format *format,
   struct strbuf *final_buf);
 /*  Print the ref using the given format and quote_style */
-void show_ref_array_item(struct ref_array_item *info, const struct ref_format 
*format);
+int show_ref_array_item(struct ref_array_item *info, const struct ref_format 
*format);
 /*  Parse a single sort specifier and add it to the list */
 void parse_ref_sorting(struct ref_sorting **sorting_tail, const char *atom);
 /*  Callback function for parsing the sort option */

--
https://github.com/git/git/pull/452


[PATCH RFC v2 17/25] ref-filter: make cat_file_info independent

2018-02-05 Thread Olga Telezhnaya
Remove connection between expand_data variable
in cat-file and in ref-filter.
It will help further to get rid of using expand_data in cat-file.

Signed-off-by: Olga Telezhnaia 
Mentored-by: Christian Couder 
Mentored by: Jeff King 
---
 builtin/cat-file.c |  2 +-
 ref-filter.c   | 29 +++--
 ref-filter.h   |  1 -
 3 files changed, 16 insertions(+), 16 deletions(-)

diff --git a/builtin/cat-file.c b/builtin/cat-file.c
index 37adf626d0e55..5b9869cdb9096 100644
--- a/builtin/cat-file.c
+++ b/builtin/cat-file.c
@@ -292,6 +292,7 @@ static void batch_object_write(const char *obj_name, struct 
batch_options *opt,
if (populate_value())
return;
 
+   data->type = item.type;
strbuf_expand(, opt->format.format, expand_format, );
strbuf_addch(, '\n');
batch_write(opt, buf.buf, buf.len);
@@ -393,7 +394,6 @@ static int batch_objects(struct batch_options *opt)
 * object.
 */
memset(, 0, sizeof(data));
-   opt->format.cat_file_data = 
opt->format.is_cat = 1;
opt->format.all_objects = opt->all_objects;
verify_ref_format(>format);
diff --git a/ref-filter.c b/ref-filter.c
index 7dcd36cd2cddc..a65a90790fd2c 100644
--- a/ref-filter.c
+++ b/ref-filter.c
@@ -100,7 +100,7 @@ static struct used_atom {
} u;
 } *used_atom;
 static int used_atom_cnt, need_tagged, need_symref;
-struct expand_data *cat_file_info;
+struct expand_data cat_file_info;
 static int is_cat = 0;
 
 static void color_atom_parser(const struct ref_format *format, struct 
used_atom *atom, const char *color_value)
@@ -256,9 +256,9 @@ static void objectname_atom_parser(const struct ref_format 
*format, struct used_
 static void objectsize_atom_parser(const struct ref_format *format, struct 
used_atom *atom, const char *arg)
 {
if (!arg)
-   cat_file_info->info.sizep = _file_info->size;
+   cat_file_info.info.sizep = _file_info.size;
else if (!strcmp(arg, "disk"))
-   cat_file_info->info.disk_sizep = _file_info->disk_size;
+   cat_file_info.info.disk_sizep = _file_info.disk_size;
else
die(_("urecognized %%(objectsize) argument: %s"), arg);
 }
@@ -266,7 +266,7 @@ static void objectsize_atom_parser(const struct ref_format 
*format, struct used_
 static void objecttype_atom_parser(const struct ref_format *format, struct 
used_atom *atom, const char *arg)
 {
if (!arg)
-   cat_file_info->info.typep = _file_info->type;
+   cat_file_info.info.typep = _file_info.type;
else
die(_("urecognized %%(objecttype) argument: %s"), arg);
 }
@@ -274,7 +274,7 @@ static void objecttype_atom_parser(const struct ref_format 
*format, struct used_
 static void deltabase_atom_parser(const struct ref_format *format, struct 
used_atom *atom, const char *arg)
 {
if (!arg)
-   cat_file_info->info.delta_base_sha1 = 
cat_file_info->delta_base_oid.hash;
+   cat_file_info.info.delta_base_sha1 = 
cat_file_info.delta_base_oid.hash;
else
die(_("urecognized %%(deltabase) argument: %s"), arg);
 }
@@ -752,7 +752,6 @@ int verify_ref_format(struct ref_format *format)
 {
const char *cp, *sp;
 
-   cat_file_info = format->cat_file_data;
is_cat = format->is_cat;
format->need_color_reset_at_eol = 0;
for (cp = format->format; *cp && (sp = find_next(cp)); ) {
@@ -779,8 +778,8 @@ int verify_ref_format(struct ref_format *format)
format->need_color_reset_at_eol = 0;
if (is_cat && format->all_objects) {
struct object_info empty = OBJECT_INFO_INIT;
-   if (!memcmp(_file_info->info, , sizeof(empty)))
-   cat_file_info->skip_object_info = 1;
+   if (!memcmp(_file_info.info, , sizeof(empty)))
+   cat_file_info.skip_object_info = 1;
}
return 0;
 }
@@ -1422,18 +1421,20 @@ static const char *get_refname(struct used_atom *atom, 
struct ref_array_item *re
 
 static int check_and_fill_for_cat(struct ref_array_item *ref)
 {
-   if (!cat_file_info->skip_object_info &&
-   sha1_object_info_extended(ref->oid.hash, _file_info->info,
+   if (!cat_file_info.info.typep)
+   cat_file_info.info.typep = _file_info.type;
+   if (!cat_file_info.skip_object_info &&
+   sha1_object_info_extended(ref->oid.hash, _file_info.info,
  OBJECT_INFO_LOOKUP_REPLACE) < 0) {
const char *e = ref->objectname;
printf("%s missing\n", e ? e : oid_to_hex(>oid));
fflush(stdout);
return -1;
}
-   ref->type = cat_file_info->type;
-   ref->size = cat_file_info->size;
-   ref->disk_size = cat_file_info->disk_size;
-   ref->delta_base_oid = 

[PATCH RFC v2 14/25] ref-filter: add is_cat flag

2018-02-05 Thread Olga Telezhnaya
Add is_cat flag, further it helps to get rid of cat_file_data field
in ref_format.

Signed-off-by: Olga Telezhnaia 
Mentored-by: Christian Couder 
Mentored by: Jeff King 
---
 builtin/cat-file.c | 1 +
 ref-filter.c   | 8 +---
 ref-filter.h   | 1 +
 3 files changed, 7 insertions(+), 3 deletions(-)

diff --git a/builtin/cat-file.c b/builtin/cat-file.c
index 179c955b86bd5..e8e788f41b890 100644
--- a/builtin/cat-file.c
+++ b/builtin/cat-file.c
@@ -395,6 +395,7 @@ static int batch_objects(struct batch_options *opt)
 */
memset(, 0, sizeof(data));
opt->format.cat_file_data = 
+   opt->format.is_cat = 1;
verify_ref_format(>format);
if (opt->cmdmode)
data.split_on_whitespace = 1;
diff --git a/ref-filter.c b/ref-filter.c
index 34a54db168265..91290b62450b3 100644
--- a/ref-filter.c
+++ b/ref-filter.c
@@ -101,6 +101,7 @@ static struct used_atom {
 } *used_atom;
 static int used_atom_cnt, need_tagged, need_symref;
 struct expand_data *cat_file_info;
+static int is_cat = 0;
 
 static void color_atom_parser(const struct ref_format *format, struct 
used_atom *atom, const char *color_value)
 {
@@ -493,7 +494,7 @@ static int parse_ref_filter_atom(const struct ref_format 
*format,
need_tagged = 1;
if (!strcmp(valid_atom[i].name, "symref"))
need_symref = 1;
-   if (cat_file_info && !strcmp(valid_atom[i].name, "rest"))
+   if (is_cat && !strcmp(valid_atom[i].name, "rest"))
cat_file_info->split_on_whitespace = 1;
return at;
 }
@@ -739,6 +740,7 @@ int verify_ref_format(struct ref_format *format)
const char *cp, *sp;
 
cat_file_info = format->cat_file_data;
+   is_cat = format->is_cat;
format->need_color_reset_at_eol = 0;
for (cp = format->format; *cp && (sp = find_next(cp)); ) {
const char *color, *ep = strchr(sp, ')');
@@ -748,7 +750,7 @@ int verify_ref_format(struct ref_format *format)
return error(_("malformed format string %s"), sp);
/* sp points at "%(" and ep points at the closing ")" */
 
-   if (format->cat_file_data)
+   if (is_cat)
at = parse_ref_filter_atom(format, valid_cat_file_atom,
   
ARRAY_SIZE(valid_cat_file_atom), sp + 2, ep);
else {
@@ -1438,7 +1440,7 @@ int populate_value(struct ref_array_item *ref)
ref->symref = "";
}
 
-   if (cat_file_info && check_and_fill_for_cat(ref))
+   if (is_cat && check_and_fill_for_cat(ref))
return -1;
 
/* Fill in specials first */
diff --git a/ref-filter.h b/ref-filter.h
index 5c6e019998716..69271e8c39f40 100644
--- a/ref-filter.h
+++ b/ref-filter.h
@@ -125,6 +125,7 @@ struct ref_format {
 * hopefully would be reduced later.
 */
struct expand_data *cat_file_data;
+   int is_cat;
 };
 
 #define REF_FORMAT_INIT { NULL, 0, -1 }

--
https://github.com/git/git/pull/452


[PATCH RFC v2 23/25] for-each-ref: tests for new atoms added

2018-02-05 Thread Olga Telezhnaya
Add tests for new formatting atoms: rest, deltabase, objectsize:disk.
rest means nothing and we expand it into empty string.
We need this atom for cat-file command.
Have plans to support deltabase and objectsize:disk further
(as it is done in cat-file), now also expand it to empty string.

Signed-off-by: Olga Telezhnaia 
Mentored-by: Christian Couder 
Mentored by: Jeff King 
---
 t/t6300-for-each-ref.sh | 18 ++
 1 file changed, 18 insertions(+)

diff --git a/t/t6300-for-each-ref.sh b/t/t6300-for-each-ref.sh
index c128dfc579079..eee656a6abba9 100755
--- a/t/t6300-for-each-ref.sh
+++ b/t/t6300-for-each-ref.sh
@@ -316,6 +316,24 @@ test_expect_success 'exercise strftime with odd fields' '
test_cmp expected actual
 '
 
+test_expect_success 'Check format %(objectsize:disk) gives empty output ' '
+   echo >expected &&
+   git for-each-ref --format="%(objectsize:disk)" refs/heads >actual &&
+   test_cmp expected actual
+'
+
+test_expect_success 'Check format %(rest) gives empty output ' '
+   echo >expected &&
+   git for-each-ref --format="%(rest)" refs/heads >actual &&
+   test_cmp expected actual
+'
+
+test_expect_success 'Check format %(deltabase) gives empty output ' '
+   echo >expected &&
+   git for-each-ref --format="%(deltabase)" refs/heads >actual &&
+   test_cmp expected actual
+'
+
 cat >expected <<\EOF
 refs/heads/master
 refs/remotes/origin/master

--
https://github.com/git/git/pull/452


[PATCH RFC v2 07/25] cat-file: start migrating formatting to ref-filter

2018-02-05 Thread Olga Telezhnaya
Move mark_atom_in_object_info() from cat-file to ref-filter and
start using it in verify_ref_format().
It also means that we start reusing verify_ref_format() in cat-file.

Start from simple moving of mark_atom_in_object_info(),
it would be removed later by integrating all needed processes into
ref-filter logic.

Signed-off-by: Olga Telezhnaia 
Mentored-by: Christian Couder 
Mentored by: Jeff King 
---
 builtin/cat-file.c | 30 +++---
 ref-filter.c   | 41 -
 ref-filter.h   | 12 ++--
 3 files changed, 45 insertions(+), 38 deletions(-)

diff --git a/builtin/cat-file.c b/builtin/cat-file.c
index edb04a96d9bd3..909412747cbd2 100644
--- a/builtin/cat-file.c
+++ b/builtin/cat-file.c
@@ -182,25 +182,6 @@ static int is_atom(const char *atom, const char *s, int 
slen)
return alen == slen && !memcmp(atom, s, alen);
 }
 
-static void mark_atom_in_object_info(const char *atom, int len,
-struct expand_data *data)
-{
-   if (is_atom("objectname", atom, len))
-   ; /* do nothing */
-   else if (is_atom("objecttype", atom, len))
-   data->info.typep = >type;
-   else if (is_atom("objectsize", atom, len))
-   data->info.sizep = >size;
-   else if (is_atom("objectsize:disk", atom, len))
-   data->info.disk_sizep = >disk_size;
-   else if (is_atom("rest", atom, len))
-   data->split_on_whitespace = 1;
-   else if (is_atom("deltabase", atom, len))
-   data->info.delta_base_sha1 = data->delta_base_oid.hash;
-   else
-   die("unknown format element: %.*s", len, atom);
-}
-
 static void expand_atom(struct strbuf *sb, const char *atom, int len,
 struct expand_data *data)
 {
@@ -230,11 +211,7 @@ static size_t expand_format(struct strbuf *sb, const char 
*start, void *vdata)
if (!end)
die("format element '%s' does not end in ')'", start);
 
-   if (data->mark_query)
-   mark_atom_in_object_info(start + 1, end - start - 1, data);
-   else
-   expand_atom(sb, start + 1, end - start - 1, data);
-
+   expand_atom(sb, start + 1, end - start - 1, data);
return end - start + 1;
 }
 
@@ -418,9 +395,8 @@ static int batch_objects(struct batch_options *opt)
 * object.
 */
memset(, 0, sizeof(data));
-   data.mark_query = 1;
-   strbuf_expand(, opt->format.format, expand_format, );
-   data.mark_query = 0;
+   opt->format.cat_file_data = 
+   verify_ref_format(>format);
if (opt->cmdmode)
data.split_on_whitespace = 1;
 
diff --git a/ref-filter.c b/ref-filter.c
index 5e7ed0f338490..ff87e632f463c 100644
--- a/ref-filter.c
+++ b/ref-filter.c
@@ -392,6 +392,31 @@ struct atom_value {
struct used_atom *atom;
 };
 
+static int is_atom(const char *atom, const char *s, int slen)
+{
+   int alen = strlen(atom);
+   return alen == slen && !memcmp(atom, s, alen);
+}
+
+static void mark_atom_in_object_info(const char *atom, int len,
+   struct expand_data *data)
+{
+   if (is_atom("objectname", atom, len))
+   ; /* do nothing */
+   else if (is_atom("objecttype", atom, len))
+   data->info.typep = >type;
+   else if (is_atom("objectsize", atom, len))
+   data->info.sizep = >size;
+   else if (is_atom("objectsize:disk", atom, len))
+   data->info.disk_sizep = >disk_size;
+   else if (is_atom("rest", atom, len))
+   data->split_on_whitespace = 1;
+   else if (is_atom("deltabase", atom, len))
+   data->info.delta_base_sha1 = data->delta_base_oid.hash;
+   else
+   die("unknown format element: %.*s", len, atom);
+}
+
 /*
  * Used to parse format string and sort specifiers
  */
@@ -709,12 +734,18 @@ int verify_ref_format(struct ref_format *format)
if (!ep)
return error(_("malformed format string %s"), sp);
/* sp points at "%(" and ep points at the closing ")" */
-   at = parse_ref_filter_atom(format, valid_atom,
-  ARRAY_SIZE(valid_atom), sp + 2, ep);
-   cp = ep + 1;
 
-   if (skip_prefix(used_atom[at].name, "color:", ))
-   format->need_color_reset_at_eol = !!strcmp(color, 
"reset");
+   if (format->cat_file_data)
+   mark_atom_in_object_info(sp + 2, ep - sp - 2,
+   format->cat_file_data);
+   else {
+   at = parse_ref_filter_atom(format, valid_atom,
+  ARRAY_SIZE(valid_atom), sp + 
2, ep);
+   if 

[PATCH RFC v2 09/25] cat-file: start use ref_array_item struct

2018-02-05 Thread Olga Telezhnaya
Moving from using expand_data to ref_array_item structure.
That helps us to reuse functions from ref-filter easier.

Signed-off-by: Olga Telezhnaia 
Mentored-by: Christian Couder 
Mentored by: Jeff King 
---
 builtin/cat-file.c | 32 
 ref-filter.h   |  5 +
 2 files changed, 25 insertions(+), 12 deletions(-)

diff --git a/builtin/cat-file.c b/builtin/cat-file.c
index 909412747cbd2..61b7acc79155d 100644
--- a/builtin/cat-file.c
+++ b/builtin/cat-file.c
@@ -183,27 +183,27 @@ static int is_atom(const char *atom, const char *s, int 
slen)
 }
 
 static void expand_atom(struct strbuf *sb, const char *atom, int len,
-struct expand_data *data)
+struct ref_array_item *item)
 {
if (is_atom("objectname", atom, len))
-   strbuf_addstr(sb, oid_to_hex(>oid));
+   strbuf_addstr(sb, oid_to_hex(>objectname));
else if (is_atom("objecttype", atom, len))
-   strbuf_addstr(sb, typename(data->type));
+   strbuf_addstr(sb, typename(item->type));
else if (is_atom("objectsize", atom, len))
-   strbuf_addf(sb, "%lu", data->size);
+   strbuf_addf(sb, "%lu", item->size);
else if (is_atom("objectsize:disk", atom, len))
-   strbuf_addf(sb, "%"PRIuMAX, (uintmax_t)data->disk_size);
+   strbuf_addf(sb, "%"PRIuMAX, (uintmax_t)item->disk_size);
else if (is_atom("rest", atom, len)) {
-   if (data->rest)
-   strbuf_addstr(sb, data->rest);
+   if (item->rest)
+   strbuf_addstr(sb, item->rest);
} else if (is_atom("deltabase", atom, len))
-   strbuf_addstr(sb, oid_to_hex(>delta_base_oid));
+   strbuf_addstr(sb, oid_to_hex(item->delta_base_oid));
 }
 
-static size_t expand_format(struct strbuf *sb, const char *start, void *vdata)
+static size_t expand_format(struct strbuf *sb, const char *start, void *data)
 {
const char *end;
-   struct expand_data *data = vdata;
+   struct ref_array_item *item = data;
 
if (*start != '(')
return 0;
@@ -211,7 +211,7 @@ static size_t expand_format(struct strbuf *sb, const char 
*start, void *vdata)
if (!end)
die("format element '%s' does not end in ')'", start);
 
-   expand_atom(sb, start + 1, end - start - 1, data);
+   expand_atom(sb, start + 1, end - start - 1, item);
return end - start + 1;
 }
 
@@ -283,6 +283,7 @@ static void batch_object_write(const char *obj_name, struct 
batch_options *opt,
   struct expand_data *data)
 {
struct strbuf buf = STRBUF_INIT;
+   struct ref_array_item item = {0};
 
if (!data->skip_object_info &&
sha1_object_info_extended(data->oid.hash, >info,
@@ -293,7 +294,14 @@ static void batch_object_write(const char *obj_name, 
struct batch_options *opt,
return;
}
 
-   strbuf_expand(, opt->format.format, expand_format, data);
+   item.objectname = data->oid;
+   item.type = data->type;
+   item.size = data->size;
+   item.disk_size = data->disk_size;
+   item.rest = data->rest;
+   item.delta_base_oid = >delta_base_oid;
+
+   strbuf_expand(, opt->format.format, expand_format, );
strbuf_addch(, '\n');
batch_write(opt, buf.buf, buf.len);
strbuf_release();
diff --git a/ref-filter.h b/ref-filter.h
index 52e07dbe6864a..781921d4e0978 100644
--- a/ref-filter.h
+++ b/ref-filter.h
@@ -40,6 +40,11 @@ struct ref_array_item {
const char *symref;
struct commit *commit;
struct atom_value *value;
+   enum object_type type;
+   unsigned long size;
+   off_t disk_size;
+   const char *rest;
+   struct object_id *delta_base_oid;
char refname[FLEX_ARRAY];
 };
 

--
https://github.com/git/git/pull/452


[PATCH RFC v2 22/25] ref-filter: work with objectsize:disk

2018-02-05 Thread Olga Telezhnaya
Make a temporary solution for commands that could use
objectsize:disk atom.
It's better to fill it with value or give an error if there is no value
for this atom, but as a first solution we do dothing.
It means that if objectsize:disk is used, we put an empty string there.

Signed-off-by: Olga Telezhnaia 
Mentored-by: Christian Couder 
Mentored by: Jeff King 
---
 ref-filter.c | 6 --
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/ref-filter.c b/ref-filter.c
index aa15dd0b4723e..b21358aea476b 100644
--- a/ref-filter.c
+++ b/ref-filter.c
@@ -826,8 +826,10 @@ static void grab_common_values(struct atom_value *val, int 
deref, struct object
v->value = sz;
v->s = xstrfmt("%lu", sz);
} else if (!strcmp(name, "objectsize:disk")) {
-   v->value = cat_file_info.disk_size;
-   v->s = xstrfmt("%"PRIuMAX, (uintmax_t)v->value);
+   if (is_cat) {
+   v->value = cat_file_info.disk_size;
+   v->s = xstrfmt("%"PRIuMAX, (uintmax_t)v->value);
+   }
} else if (deref)
grab_objectname(name, obj->oid.hash, v, _atom[i]);
}

--
https://github.com/git/git/pull/452


[PATCH RFC v2 05/25] cat-file: move struct expand_data into ref-filter

2018-02-05 Thread Olga Telezhnaya
Need that for further reusing of formatting logic in cat-file.
Have plans to get rid of using expand_data in cat-file at all,
and use it only in ref-filter for collecting, formatting and printing
needed data.

Signed-off-by: Olga Telezhnaia 
Mentored-by: Christian Couder 
Mentored by: Jeff King 
---
 builtin/cat-file.c | 36 
 ref-filter.h   | 36 
 2 files changed, 36 insertions(+), 36 deletions(-)

diff --git a/builtin/cat-file.c b/builtin/cat-file.c
index 98fc5ec069a49..37d6096d201b5 100644
--- a/builtin/cat-file.c
+++ b/builtin/cat-file.c
@@ -176,42 +176,6 @@ static int cat_one_file(int opt, const char *exp_type, 
const char *obj_name,
return 0;
 }
 
-struct expand_data {
-   struct object_id oid;
-   enum object_type type;
-   unsigned long size;
-   off_t disk_size;
-   const char *rest;
-   struct object_id delta_base_oid;
-
-   /*
-* If mark_query is true, we do not expand anything, but rather
-* just mark the object_info with items we wish to query.
-*/
-   int mark_query;
-
-   /*
-* Whether to split the input on whitespace before feeding it to
-* get_sha1; this is decided during the mark_query phase based on
-* whether we have a %(rest) token in our format.
-*/
-   int split_on_whitespace;
-
-   /*
-* After a mark_query run, this object_info is set up to be
-* passed to sha1_object_info_extended. It will point to the data
-* elements above, so you can retrieve the response from there.
-*/
-   struct object_info info;
-
-   /*
-* This flag will be true if the requested batch format and options
-* don't require us to call sha1_object_info, which can then be
-* optimized out.
-*/
-   unsigned skip_object_info : 1;
-};
-
 static int is_atom(const char *atom, const char *s, int slen)
 {
int alen = strlen(atom);
diff --git a/ref-filter.h b/ref-filter.h
index b75c8ac45248e..17f2ac24d2739 100644
--- a/ref-filter.h
+++ b/ref-filter.h
@@ -72,6 +72,42 @@ struct ref_filter {
verbose;
 };
 
+struct expand_data {
+   struct object_id oid;
+   enum object_type type;
+   unsigned long size;
+   off_t disk_size;
+   const char *rest;
+   struct object_id delta_base_oid;
+
+   /*
+* If mark_query is true, we do not expand anything, but rather
+* just mark the object_info with items we wish to query.
+*/
+   int mark_query;
+
+   /*
+* Whether to split the input on whitespace before feeding it to
+* get_sha1; this is decided during the mark_query phase based on
+* whether we have a %(rest) token in our format.
+*/
+   int split_on_whitespace;
+
+   /*
+* After a mark_query run, this object_info is set up to be
+* passed to sha1_object_info_extended. It will point to the data
+* elements above, so you can retrieve the response from there.
+*/
+   struct object_info info;
+
+   /*
+* This flag will be true if the requested batch format and options
+* don't require us to call sha1_object_info, which can then be
+* optimized out.
+*/
+   unsigned skip_object_info : 1;
+};
+
 struct ref_format {
/*
 * Set these to define the format; make sure you call

--
https://github.com/git/git/pull/452


[PATCH RFC v2 08/25] ref-filter: reuse parse_ref_filter_atom()

2018-02-05 Thread Olga Telezhnaya
Continue migrating formatting logic from cat-file to ref-filter.
Reuse parse_ref_filter_atom() for unifying all processes in ref-filter
and further removing of mark_atom_in_object_info().

Signed-off-by: Olga Telezhnaia 
Mentored-by: Christian Couder 
Mentored by: Jeff King 
---
 ref-filter.c | 34 +-
 1 file changed, 25 insertions(+), 9 deletions(-)

diff --git a/ref-filter.c b/ref-filter.c
index ff87e632f463c..5c75259b1ab8c 100644
--- a/ref-filter.c
+++ b/ref-filter.c
@@ -100,6 +100,7 @@ static struct used_atom {
} u;
 } *used_atom;
 static int used_atom_cnt, need_tagged, need_symref;
+struct expand_data *cat_file_info;
 
 static void color_atom_parser(const struct ref_format *format, struct 
used_atom *atom, const char *color_value)
 {
@@ -251,6 +252,16 @@ static void objectname_atom_parser(const struct ref_format 
*format, struct used_
die(_("unrecognized %%(objectname) argument: %s"), arg);
 }
 
+static void objectsize_atom_parser(const struct ref_format *format, struct 
used_atom *atom, const char *arg)
+{
+   if (!arg)
+   ; /* default to normal object size */
+   else if (!strcmp(arg, "disk"))
+   cat_file_info->info.disk_sizep = _file_info->disk_size;
+   else
+   die(_("urecognized %%(objectsize) argument: %s"), arg);
+}
+
 static void refname_atom_parser(const struct ref_format *format, struct 
used_atom *atom, const char *arg)
 {
refname_atom_parser_internal(>u.refname, arg, atom->name);
@@ -371,6 +382,14 @@ static struct valid_atom {
{ "else" },
 };
 
+static struct valid_atom valid_cat_file_atom[] = {
+   { "objectname" },
+   { "objecttype" },
+   { "objectsize", FIELD_ULONG, objectsize_atom_parser },
+   { "rest" },
+   { "deltabase" },
+};
+
 #define REF_FORMATTING_STATE_INIT  { 0, NULL }
 
 struct ref_formatting_stack {
@@ -401,20 +420,14 @@ static int is_atom(const char *atom, const char *s, int 
slen)
 static void mark_atom_in_object_info(const char *atom, int len,
struct expand_data *data)
 {
-   if (is_atom("objectname", atom, len))
-   ; /* do nothing */
-   else if (is_atom("objecttype", atom, len))
+   if (is_atom("objecttype", atom, len))
data->info.typep = >type;
else if (is_atom("objectsize", atom, len))
data->info.sizep = >size;
-   else if (is_atom("objectsize:disk", atom, len))
-   data->info.disk_sizep = >disk_size;
else if (is_atom("rest", atom, len))
data->split_on_whitespace = 1;
else if (is_atom("deltabase", atom, len))
data->info.delta_base_sha1 = data->delta_base_oid.hash;
-   else
-   die("unknown format element: %.*s", len, atom);
 }
 
 /*
@@ -483,6 +496,8 @@ static int parse_ref_filter_atom(const struct ref_format 
*format,
need_tagged = 1;
if (!strcmp(valid_atom[i].name, "symref"))
need_symref = 1;
+   if (cat_file_info)
+   mark_atom_in_object_info(atom, atom_len, cat_file_info);
return at;
 }
 
@@ -726,6 +741,7 @@ int verify_ref_format(struct ref_format *format)
 {
const char *cp, *sp;
 
+   cat_file_info = format->cat_file_data;
format->need_color_reset_at_eol = 0;
for (cp = format->format; *cp && (sp = find_next(cp)); ) {
const char *color, *ep = strchr(sp, ')');
@@ -736,8 +752,8 @@ int verify_ref_format(struct ref_format *format)
/* sp points at "%(" and ep points at the closing ")" */
 
if (format->cat_file_data)
-   mark_atom_in_object_info(sp + 2, ep - sp - 2,
-   format->cat_file_data);
+   at = parse_ref_filter_atom(format, valid_cat_file_atom,
+  
ARRAY_SIZE(valid_cat_file_atom), sp + 2, ep);
else {
at = parse_ref_filter_atom(format, valid_atom,
   ARRAY_SIZE(valid_atom), sp + 
2, ep);

--
https://github.com/git/git/pull/452


[PATCH RFC v2 20/25] ref-filter: make populate_value() internal again

2018-02-05 Thread Olga Telezhnaya
Remove populate_value() from header file. We needed that
for interim step, now it could be returned back.

Signed-off-by: Olga Telezhnaia 
Mentored-by: Christian Couder 
Mentored by: Jeff King 
---
 ref-filter.c | 2 +-
 ref-filter.h | 3 ---
 2 files changed, 1 insertion(+), 4 deletions(-)

diff --git a/ref-filter.c b/ref-filter.c
index e34580e8db508..70c685851466b 100644
--- a/ref-filter.c
+++ b/ref-filter.c
@@ -1429,7 +1429,7 @@ static int check_and_fill_for_cat(struct ref_array_item 
*ref)
  * Parse the object referred by ref, and grab needed value.
  * Return 0 if everything was successful, -1 otherwise.
  */
-int populate_value(struct ref_array_item *ref)
+static int populate_value(struct ref_array_item *ref)
 {
void *buf;
struct object *obj;
diff --git a/ref-filter.h b/ref-filter.h
index 244a27bfc4e12..c0edb17aa404a 100644
--- a/ref-filter.h
+++ b/ref-filter.h
@@ -177,9 +177,6 @@ void setup_ref_filter_porcelain_msg(void);
 void pretty_print_ref(const char *name, const unsigned char *sha1,
  const struct ref_format *format);
 
-/* Fill the values of request and prepare all data for final string creation */
-int populate_value(struct ref_array_item *ref);
-
 /* Search for atom in given format. */
 int is_atom_used(const struct ref_format *format, const char *atom);
 

--
https://github.com/git/git/pull/452


[PATCH RFC v2 04/25] ref-filter: make valid_atom as function parameter

2018-02-05 Thread Olga Telezhnaya
Make valid_atom as a function parameter,
there could be another variable further.
Need that for further reusing of formatting logic in cat-file.c.

We do not need to allow users to pass their own valid_atom variable in
global functions like verify_ref_format() because in the end we want to
have same set of valid atoms for all commands. But, as a first step
of migrating, I create further another version of valid_atom
for cat-file.

Signed-off-by: Olga Telezhnaia 
Mentored-by: Christian Couder 
Mentored by: Jeff King 
---
 ref-filter.c | 17 +++--
 1 file changed, 11 insertions(+), 6 deletions(-)

diff --git a/ref-filter.c b/ref-filter.c
index 9ed5e66066a7a..5e7ed0f338490 100644
--- a/ref-filter.c
+++ b/ref-filter.c
@@ -325,7 +325,7 @@ static void head_atom_parser(const struct ref_format 
*format, struct used_atom *
atom->u.head = resolve_refdup("HEAD", RESOLVE_REF_READING, NULL, NULL);
 }
 
-static struct {
+static struct valid_atom {
const char *name;
cmp_type cmp_type;
void (*parser)(const struct ref_format *format, struct used_atom *atom, 
const char *arg);
@@ -396,6 +396,7 @@ struct atom_value {
  * Used to parse format string and sort specifiers
  */
 static int parse_ref_filter_atom(const struct ref_format *format,
+const struct valid_atom *valid_atom, int 
n_atoms,
 const char *atom, const char *ep)
 {
const char *sp;
@@ -425,13 +426,13 @@ static int parse_ref_filter_atom(const struct ref_format 
*format,
atom_len = (arg ? arg : ep) - sp;
 
/* Is the atom a valid one? */
-   for (i = 0; i < ARRAY_SIZE(valid_atom); i++) {
+   for (i = 0; i < n_atoms; i++) {
int len = strlen(valid_atom[i].name);
if (len == atom_len && !memcmp(valid_atom[i].name, sp, len))
break;
}
 
-   if (ARRAY_SIZE(valid_atom) <= i)
+   if (n_atoms <= i)
die(_("unknown field name: %.*s"), (int)(ep-atom), atom);
 
/* Add it in, including the deref prefix */
@@ -708,7 +709,8 @@ int verify_ref_format(struct ref_format *format)
if (!ep)
return error(_("malformed format string %s"), sp);
/* sp points at "%(" and ep points at the closing ")" */
-   at = parse_ref_filter_atom(format, sp + 2, ep);
+   at = parse_ref_filter_atom(format, valid_atom,
+  ARRAY_SIZE(valid_atom), sp + 2, ep);
cp = ep + 1;
 
if (skip_prefix(used_atom[at].name, "color:", ))
@@ -2145,7 +2147,9 @@ int format_ref_array_item(struct ref_array_item *info,
if (cp < sp)
append_literal(cp, sp, );
if (get_ref_atom_value(info,
-  parse_ref_filter_atom(format, sp + 2, 
ep),
+  parse_ref_filter_atom(format, valid_atom,
+
ARRAY_SIZE(valid_atom),
+sp + 2, ep),
   ))
return -1;
atomv->handler(atomv, );
@@ -2198,7 +2202,8 @@ static int parse_sorting_atom(const char *atom)
 */
struct ref_format dummy = REF_FORMAT_INIT;
const char *end = atom + strlen(atom);
-   return parse_ref_filter_atom(, atom, end);
+   return parse_ref_filter_atom(, valid_atom,
+ARRAY_SIZE(valid_atom), atom, end);
 }
 
 /*  If no sorting option is given, use refname to sort as default */

--
https://github.com/git/git/pull/452


[PATCH RFC v2 15/25] ref_filter: add is_atom_used function

2018-02-05 Thread Olga Telezhnaya
Delete all items related to split_on_whitespace from ref-filter
and add new function for handling the logic.
Now cat-file could invoke that function to implementing its logic.

Signed-off-by: Olga Telezhnaia 
Mentored-by: Christian Couder 
Mentored by: Jeff King 
---
 builtin/cat-file.c |  8 +++-
 ref-filter.c   | 17 +++--
 ref-filter.h   | 10 +++---
 3 files changed, 21 insertions(+), 14 deletions(-)

diff --git a/builtin/cat-file.c b/builtin/cat-file.c
index e8e788f41b890..a55138f1fd1d1 100644
--- a/builtin/cat-file.c
+++ b/builtin/cat-file.c
@@ -382,8 +382,7 @@ static int batch_objects(struct batch_options *opt)
 {
struct strbuf buf = STRBUF_INIT;
struct expand_data data;
-   int save_warning;
-   int retval = 0;
+   int save_warning, is_rest, retval = 0;
 
if (!opt->format.format)
opt->format.format = "%(objectname) %(objecttype) 
%(objectsize)";
@@ -397,8 +396,6 @@ static int batch_objects(struct batch_options *opt)
opt->format.cat_file_data = 
opt->format.is_cat = 1;
verify_ref_format(>format);
-   if (opt->cmdmode)
-   data.split_on_whitespace = 1;
 
if (opt->all_objects) {
struct object_info empty = OBJECT_INFO_INIT;
@@ -437,9 +434,10 @@ static int batch_objects(struct batch_options *opt)
 */
save_warning = warn_on_object_refname_ambiguity;
warn_on_object_refname_ambiguity = 0;
+   is_rest = opt->cmdmode || is_atom_used(>format, "rest");
 
while (strbuf_getline(, stdin) != EOF) {
-   if (data.split_on_whitespace) {
+   if (is_rest) {
/*
 * Split at first whitespace, tying off the beginning
 * of the string and saving the remainder (or NULL) in
diff --git a/ref-filter.c b/ref-filter.c
index 91290b62450b3..bbcd507d179a9 100644
--- a/ref-filter.c
+++ b/ref-filter.c
@@ -494,8 +494,6 @@ static int parse_ref_filter_atom(const struct ref_format 
*format,
need_tagged = 1;
if (!strcmp(valid_atom[i].name, "symref"))
need_symref = 1;
-   if (is_cat && !strcmp(valid_atom[i].name, "rest"))
-   cat_file_info->split_on_whitespace = 1;
return at;
 }
 
@@ -731,6 +729,21 @@ static const char *find_next(const char *cp)
return NULL;
 }
 
+/* Search for atom in given format. */
+int is_atom_used(const struct ref_format *format, const char *atom)
+{
+   const char *cp, *sp;
+   for (cp = format->format; *cp && (sp = find_next(cp)); ) {
+   const char *ep = strchr(sp, ')');
+   int atom_len = ep - sp - 2;
+   sp += 2;
+   if (atom_len == strlen(atom) && !memcmp(sp, atom, atom_len))
+   return 1;
+   cp = ep + 1;
+   }
+   return 0;
+}
+
 /*
  * Make sure the format string is well formed, and parse out
  * the used atoms.
diff --git a/ref-filter.h b/ref-filter.h
index 69271e8c39f40..f590e5d694df4 100644
--- a/ref-filter.h
+++ b/ref-filter.h
@@ -86,13 +86,6 @@ struct expand_data {
const char *rest;
struct object_id delta_base_oid;
 
-   /*
-* Whether to split the input on whitespace before feeding it to
-* get_sha1; this is decided during the mark_query phase based on
-* whether we have a %(rest) token in our format.
-*/
-   int split_on_whitespace;
-
/*
 * After a mark_query run, this object_info is set up to be
 * passed to sha1_object_info_extended. It will point to the data
@@ -187,4 +180,7 @@ void pretty_print_ref(const char *name, const unsigned char 
*sha1,
 /* Fill the values of request and prepare all data for final string creation */
 int populate_value(struct ref_array_item *ref);
 
+/* Search for atom in given format. */
+int is_atom_used(const struct ref_format *format, const char *atom);
+
 #endif /*  REF_FILTER_H  */

--
https://github.com/git/git/pull/452


[PATCH RFC v2 19/25] cat-file: reuse printing logic from ref-filter

2018-02-05 Thread Olga Telezhnaya
Reuse code from ref-filter to print resulting message.

Signed-off-by: Olga Telezhnaia 
Mentored-by: Christian Couder 
Mentored by: Jeff King 
---
 builtin/cat-file.c | 51 ---
 ref-filter.c   | 21 +++--
 2 files changed, 23 insertions(+), 49 deletions(-)

diff --git a/builtin/cat-file.c b/builtin/cat-file.c
index 5b9869cdb9096..746b02ff150a7 100644
--- a/builtin/cat-file.c
+++ b/builtin/cat-file.c
@@ -176,45 +176,6 @@ static int cat_one_file(int opt, const char *exp_type, 
const char *obj_name,
return 0;
 }
 
-static int is_atom(const char *atom, const char *s, int slen)
-{
-   int alen = strlen(atom);
-   return alen == slen && !memcmp(atom, s, alen);
-}
-
-static void expand_atom(struct strbuf *sb, const char *atom, int len,
-struct ref_array_item *item)
-{
-   if (is_atom("objectname", atom, len))
-   strbuf_addstr(sb, oid_to_hex(>oid));
-   else if (is_atom("objecttype", atom, len))
-   strbuf_addstr(sb, typename(item->type));
-   else if (is_atom("objectsize", atom, len))
-   strbuf_addf(sb, "%lu", item->size);
-   else if (is_atom("objectsize:disk", atom, len))
-   strbuf_addf(sb, "%"PRIuMAX, (uintmax_t)item->disk_size);
-   else if (is_atom("rest", atom, len)) {
-   if (item->rest)
-   strbuf_addstr(sb, item->rest);
-   } else if (is_atom("deltabase", atom, len))
-   strbuf_addstr(sb, oid_to_hex(item->delta_base_oid));
-}
-
-static size_t expand_format(struct strbuf *sb, const char *start, void *data)
-{
-   const char *end;
-   struct ref_array_item *item = data;
-
-   if (*start != '(')
-   return 0;
-   end = strchr(start + 1, ')');
-   if (!end)
-   die("format element '%s' does not end in ')'", start);
-
-   expand_atom(sb, start + 1, end - start - 1, item);
-   return end - start + 1;
-}
-
 static void batch_write(struct batch_options *opt, const void *data, int len)
 {
if (opt->buffer_output) {
@@ -282,23 +243,19 @@ static void print_object_or_die(struct batch_options 
*opt, struct expand_data *d
 static void batch_object_write(const char *obj_name, struct batch_options *opt,
   struct expand_data *data)
 {
-   struct strbuf buf = STRBUF_INIT;
struct ref_array_item item = {0};
 
item.oid = data->oid;
item.rest = data->rest;
item.objectname = obj_name;
 
-   if (populate_value())
+   if (show_ref_array_item(, >format))
return;
-
-   data->type = item.type;
-   strbuf_expand(, opt->format.format, expand_format, );
-   strbuf_addch(, '\n');
-   batch_write(opt, buf.buf, buf.len);
-   strbuf_release();
+   if (!opt->buffer_output)
+   fflush(stdout);
 
if (opt->print_contents) {
+   data->type = item.type;
print_object_or_die(opt, data);
batch_write(opt, "\n", 1);
}
diff --git a/ref-filter.c b/ref-filter.c
index 3f3583ac515a5..e34580e8db508 100644
--- a/ref-filter.c
+++ b/ref-filter.c
@@ -1466,7 +1466,21 @@ int populate_value(struct ref_array_item *ref)
name++;
}
 
-   if (starts_with(name, "refname"))
+   if (is_cat) {
+   if (starts_with(name, "objectname"))
+   v->s = oid_to_hex(>oid);
+   else if (starts_with(name, "objecttype"))
+   v->s = typename(ref->type);
+   else if (starts_with(name, "objectsize")) {
+   v->s = xstrfmt("%lu", ref->size);
+   } else if (starts_with(name, "objectsize:disk")) {
+   v->s = xstrfmt("%"PRIuMAX, 
(uintmax_t)ref->disk_size);
+   } else if (starts_with(name, "rest"))
+   v->s = ref->rest;
+   else if (starts_with(name, "deltabase"))
+   v->s = xstrdup(oid_to_hex(ref->delta_base_oid));
+   continue;
+   } else if (starts_with(name, "refname"))
refname = get_refname(atom, ref);
else if (starts_with(name, "symref"))
refname = get_symref(atom, ref);
@@ -2208,6 +,7 @@ int format_ref_array_item(struct ref_array_item *info,
 {
const char *cp, *sp, *ep;
struct ref_formatting_state state = REF_FORMATTING_STATE_INIT;
+   int retval = 0;
 
state.quote_style = format->quote_style;
push_stack_element();
@@ -2224,6 +2239,8 @@ int format_ref_array_item(struct ref_array_item *info,
return -1;
atomv->handler(atomv, );
}
+   

[PATCH RFC v2 18/25] ref-filter: make valid_atom general again

2018-02-05 Thread Olga Telezhnaya
Stop using valid_cat_file_atom, making the code more general.
Further commits will contain some tests, docs and
support of new features.

Signed-off-by: Olga Telezhnaia 
Mentored-by: Christian Couder 
Mentored by: Jeff King 
---
 ref-filter.c | 34 +-
 1 file changed, 9 insertions(+), 25 deletions(-)

diff --git a/ref-filter.c b/ref-filter.c
index a65a90790fd2c..3f3583ac515a5 100644
--- a/ref-filter.c
+++ b/ref-filter.c
@@ -359,8 +359,8 @@ static struct valid_atom {
void (*parser)(const struct ref_format *format, struct used_atom *atom, 
const char *arg);
 } valid_atom[] = {
{ "refname" , FIELD_STR, refname_atom_parser },
-   { "objecttype" },
-   { "objectsize", FIELD_ULONG },
+   { "objecttype", FIELD_STR, objecttype_atom_parser },
+   { "objectsize", FIELD_ULONG, objectsize_atom_parser },
{ "objectname", FIELD_STR, objectname_atom_parser },
{ "tree" },
{ "parent" },
@@ -397,12 +397,6 @@ static struct valid_atom {
{ "if", FIELD_STR, if_atom_parser },
{ "then" },
{ "else" },
-};
-
-static struct valid_atom valid_cat_file_atom[] = {
-   { "objectname" },
-   { "objecttype", FIELD_STR, objecttype_atom_parser },
-   { "objectsize", FIELD_ULONG, objectsize_atom_parser },
{ "rest" },
{ "deltabase", FIELD_STR, deltabase_atom_parser },
 };
@@ -432,7 +426,6 @@ struct atom_value {
  * Used to parse format string and sort specifiers
  */
 static int parse_ref_filter_atom(const struct ref_format *format,
-const struct valid_atom *valid_atom, int 
n_atoms,
 const char *atom, const char *ep)
 {
const char *sp;
@@ -462,13 +455,13 @@ static int parse_ref_filter_atom(const struct ref_format 
*format,
atom_len = (arg ? arg : ep) - sp;
 
/* Is the atom a valid one? */
-   for (i = 0; i < n_atoms; i++) {
+   for (i = 0; i < ARRAY_SIZE(valid_atom); i++) {
int len = strlen(valid_atom[i].name);
if (len == atom_len && !memcmp(valid_atom[i].name, sp, len))
break;
}
 
-   if (n_atoms <= i)
+   if (ARRAY_SIZE(valid_atom) <= i)
die(_("unknown field name: %.*s"), (int)(ep-atom), atom);
 
/* Add it in, including the deref prefix */
@@ -762,15 +755,9 @@ int verify_ref_format(struct ref_format *format)
return error(_("malformed format string %s"), sp);
/* sp points at "%(" and ep points at the closing ")" */
 
-   if (is_cat)
-   at = parse_ref_filter_atom(format, valid_cat_file_atom,
-  
ARRAY_SIZE(valid_cat_file_atom), sp + 2, ep);
-   else {
-   at = parse_ref_filter_atom(format, valid_atom,
-  ARRAY_SIZE(valid_atom), sp + 
2, ep);
-   if (skip_prefix(used_atom[at].name, "color:", ))
-   format->need_color_reset_at_eol = 
!!strcmp(color, "reset");
-   }
+   at = parse_ref_filter_atom(format, sp + 2, ep);
+   if (skip_prefix(used_atom[at].name, "color:", ))
+   format->need_color_reset_at_eol = !!strcmp(color, 
"reset");
 
cp = ep + 1;
}
@@ -2232,9 +2219,7 @@ int format_ref_array_item(struct ref_array_item *info,
if (cp < sp)
append_literal(cp, sp, );
if (get_ref_atom_value(info,
-  parse_ref_filter_atom(format, valid_atom,
-
ARRAY_SIZE(valid_atom),
-sp + 2, ep),
+  parse_ref_filter_atom(format, sp + 2, 
ep),
   ))
return -1;
atomv->handler(atomv, );
@@ -2287,8 +2272,7 @@ static int parse_sorting_atom(const char *atom)
 */
struct ref_format dummy = REF_FORMAT_INIT;
const char *end = atom + strlen(atom);
-   return parse_ref_filter_atom(, valid_atom,
-ARRAY_SIZE(valid_atom), atom, end);
+   return parse_ref_filter_atom(, atom, end);
 }
 
 /*  If no sorting option is given, use refname to sort as default */

--
https://github.com/git/git/pull/452


[PATCH RFC v2 25/25] cat-file: update of docs

2018-02-05 Thread Olga Telezhnaya
Update the docs for cat-file command. Some new formatting atoms added
because of reusing ref-filter code.
We do not support cat-file atoms in general formatting logic
(there is just the support for cat-file), that is why some of the atoms
are still explained in cat-file docs.
We need to move these explanations when atoms will be supported
by other commands.

Signed-off-by: Olga Telezhnaia 
Mentored-by: Christian Couder 
Mentored by: Jeff King 
---
 Documentation/git-cat-file.txt | 13 ++---
 1 file changed, 2 insertions(+), 11 deletions(-)

diff --git a/Documentation/git-cat-file.txt b/Documentation/git-cat-file.txt
index f90f09b03fae5..90639ac21d0e8 100644
--- a/Documentation/git-cat-file.txt
+++ b/Documentation/git-cat-file.txt
@@ -187,17 +187,8 @@ linkgit:git-rev-parse[1].
 You can specify the information shown for each object by using a custom
 ``. The `` is copied literally to stdout for each
 object, with placeholders of the form `%(atom)` expanded, followed by a
-newline. The available atoms are:
-
-`objectname`::
-   The 40-hex object name of the object.
-
-`objecttype`::
-   The type of the object (the same as `cat-file -t` reports).
-
-`objectsize`::
-   The size, in bytes, of the object (the same as `cat-file -s`
-   reports).
+newline. The available atoms are the same as that of
+linkgit:git-for-each-ref[1], but there are some additional ones:
 
 `objectsize:disk`::
The size, in bytes, that the object takes up on disk. See the

--
https://github.com/git/git/pull/452


[PATCH RFC v2 12/25] cat-file: start reusing populate_value()

2018-02-05 Thread Olga Telezhnaya
Move logic related to getting object info from cat-file to ref-filter.
It will help to reuse whole formatting logic from ref-filter further.

Signed-off-by: Olga Telezhnaia 
Mentored-by: Christian Couder 
Mentored by: Jeff King 
---
 builtin/cat-file.c | 17 -
 ref-filter.c   | 20 
 ref-filter.h   |  1 +
 3 files changed, 25 insertions(+), 13 deletions(-)

diff --git a/builtin/cat-file.c b/builtin/cat-file.c
index 367b1bd5802dc..179c955b86bd5 100644
--- a/builtin/cat-file.c
+++ b/builtin/cat-file.c
@@ -285,21 +285,12 @@ static void batch_object_write(const char *obj_name, 
struct batch_options *opt,
struct strbuf buf = STRBUF_INIT;
struct ref_array_item item = {0};
 
-   if (!data->skip_object_info &&
-   sha1_object_info_extended(data->oid.hash, >info,
- OBJECT_INFO_LOOKUP_REPLACE) < 0) {
-   printf("%s missing\n",
-  obj_name ? obj_name : oid_to_hex(>oid));
-   fflush(stdout);
-   return;
-   }
-
item.oid = data->oid;
-   item.type = data->type;
-   item.size = data->size;
-   item.disk_size = data->disk_size;
item.rest = data->rest;
-   item.delta_base_oid = >delta_base_oid;
+   item.objectname = obj_name;
+
+   if (populate_value())
+   return;
 
strbuf_expand(, opt->format.format, expand_format, );
strbuf_addch(, '\n');
diff --git a/ref-filter.c b/ref-filter.c
index d09ec1bde6d54..3f92a27d98b6c 100644
--- a/ref-filter.c
+++ b/ref-filter.c
@@ -1403,6 +1403,23 @@ static const char *get_refname(struct used_atom *atom, 
struct ref_array_item *re
return show_ref(>u.refname, ref->refname);
 }
 
+static int check_and_fill_for_cat(struct ref_array_item *ref)
+{
+   if (!cat_file_info->skip_object_info &&
+   sha1_object_info_extended(ref->oid.hash, _file_info->info,
+ OBJECT_INFO_LOOKUP_REPLACE) < 0) {
+   const char *e = ref->objectname;
+   printf("%s missing\n", e ? e : oid_to_hex(>oid));
+   fflush(stdout);
+   return -1;
+   }
+   ref->type = cat_file_info->type;
+   ref->size = cat_file_info->size;
+   ref->disk_size = cat_file_info->disk_size;
+   ref->delta_base_oid = _file_info->delta_base_oid;
+   return 0;
+}
+
 /*
  * Parse the object referred by ref, and grab needed value.
  * Return 0 if everything was successful, -1 otherwise.
@@ -1424,6 +1441,9 @@ int populate_value(struct ref_array_item *ref)
ref->symref = "";
}
 
+   if (cat_file_info && check_and_fill_for_cat(ref))
+   return -1;
+
/* Fill in specials first */
for (i = 0; i < used_atom_cnt; i++) {
struct used_atom *atom = _atom[i];
diff --git a/ref-filter.h b/ref-filter.h
index 87b026b8b76d0..5c6e019998716 100644
--- a/ref-filter.h
+++ b/ref-filter.h
@@ -45,6 +45,7 @@ struct ref_array_item {
off_t disk_size;
const char *rest;
struct object_id *delta_base_oid;
+   const char *objectname;
char refname[FLEX_ARRAY];
 };
 

--
https://github.com/git/git/pull/452


[PATCH RFC v2 03/25] cat-file: reuse struct ref_format

2018-02-05 Thread Olga Telezhnaya
Start using ref_format struct instead of simple char*.
Need that for further reusing of formatting logic from ref-filter.

Signed-off-by: Olga Telezhnaia 
Mentored-by: Christian Couder 
Mentored by: Jeff King 
---
 builtin/cat-file.c | 15 ---
 1 file changed, 8 insertions(+), 7 deletions(-)

diff --git a/builtin/cat-file.c b/builtin/cat-file.c
index f5fa4fd75af26..98fc5ec069a49 100644
--- a/builtin/cat-file.c
+++ b/builtin/cat-file.c
@@ -13,15 +13,16 @@
 #include "tree-walk.h"
 #include "sha1-array.h"
 #include "packfile.h"
+#include "ref-filter.h"
 
 struct batch_options {
+   struct ref_format format;
int enabled;
int follow_symlinks;
int print_contents;
int buffer_output;
int all_objects;
int cmdmode; /* may be 'w' or 'c' for --filters or --textconv */
-   const char *format;
 };
 
 static const char *force_path;
@@ -348,7 +349,7 @@ static void batch_object_write(const char *obj_name, struct 
batch_options *opt,
return;
}
 
-   strbuf_expand(, opt->format, expand_format, data);
+   strbuf_expand(, opt->format.format, expand_format, data);
strbuf_addch(, '\n');
batch_write(opt, buf.buf, buf.len);
strbuf_release();
@@ -441,8 +442,8 @@ static int batch_objects(struct batch_options *opt)
int save_warning;
int retval = 0;
 
-   if (!opt->format)
-   opt->format = "%(objectname) %(objecttype) %(objectsize)";
+   if (!opt->format.format)
+   opt->format.format = "%(objectname) %(objecttype) 
%(objectsize)";
 
/*
 * Expand once with our special mark_query flag, which will prime the
@@ -451,7 +452,7 @@ static int batch_objects(struct batch_options *opt)
 */
memset(, 0, sizeof(data));
data.mark_query = 1;
-   strbuf_expand(, opt->format, expand_format, );
+   strbuf_expand(, opt->format.format, expand_format, );
data.mark_query = 0;
if (opt->cmdmode)
data.split_on_whitespace = 1;
@@ -543,7 +544,7 @@ static int batch_option_callback(const struct option *opt,
 
bo->enabled = 1;
bo->print_contents = !strcmp(opt->long_name, "batch");
-   bo->format = arg;
+   bo->format.format = arg;
 
return 0;
 }
@@ -552,7 +553,7 @@ int cmd_cat_file(int argc, const char **argv, const char 
*prefix)
 {
int opt = 0;
const char *exp_type = NULL, *obj_name = NULL;
-   struct batch_options batch = {0};
+   struct batch_options batch = { REF_FORMAT_INIT };
int unknown_type = 0;
 
const struct option options[] = {

--
https://github.com/git/git/pull/452


[PATCH RFC v2 02/25] ref-filter: add return value to some functions

2018-02-05 Thread Olga Telezhnaya
Add return flag to format_ref_array_item(), show_ref_array_item(),
get_ref_array_info() and populate_value() for further using.
Need it to handle situations when item is broken but we can not invoke
die() because we are in batch mode and all items need to be processed.

Signed-off-by: Olga Telezhnaia 
Mentored-by: Christian Couder 
Mentored by: Jeff King 
---
 ref-filter.c | 37 -
 ref-filter.h | 14 ++
 2 files changed, 34 insertions(+), 17 deletions(-)

diff --git a/ref-filter.c b/ref-filter.c
index d04295e33448e..9ed5e66066a7a 100644
--- a/ref-filter.c
+++ b/ref-filter.c
@@ -1356,8 +1356,9 @@ static const char *get_refname(struct used_atom *atom, 
struct ref_array_item *re
 
 /*
  * Parse the object referred by ref, and grab needed value.
+ * Return 0 if everything was successful, -1 otherwise.
  */
-static void populate_value(struct ref_array_item *ref)
+static int populate_value(struct ref_array_item *ref)
 {
void *buf;
struct object *obj;
@@ -1482,7 +1483,7 @@ static void populate_value(struct ref_array_item *ref)
}
}
if (used_atom_cnt <= i)
-   return;
+   return 0;
 
buf = get_obj(>objectname, , , );
if (!buf)
@@ -1501,7 +1502,7 @@ static void populate_value(struct ref_array_item *ref)
 * object, we are done.
 */
if (!need_tagged || (obj->type != OBJ_TAG))
-   return;
+   return 0;
 
/*
 * If it is a tag object, see if we use a value that derefs
@@ -1525,19 +1526,24 @@ static void populate_value(struct ref_array_item *ref)
grab_values(ref->value, 1, obj, buf, size);
if (!eaten)
free(buf);
+
+   return 0;
 }
 
 /*
  * Given a ref, return the value for the atom.  This lazily gets value
  * out of the object by calling populate value.
+ * Return 0 if everything was successful, -1 otherwise.
  */
-static void get_ref_atom_value(struct ref_array_item *ref, int atom, struct 
atom_value **v)
+static int get_ref_atom_value(struct ref_array_item *ref, int atom, struct 
atom_value **v)
 {
+   int retval = 0;
if (!ref->value) {
-   populate_value(ref);
+   retval = populate_value(ref);
fill_missing_values(ref->value);
}
*v = >value[atom];
+   return retval;
 }
 
 /*
@@ -2122,7 +2128,7 @@ static void append_literal(const char *cp, const char 
*ep, struct ref_formatting
}
 }
 
-void format_ref_array_item(struct ref_array_item *info,
+int format_ref_array_item(struct ref_array_item *info,
   const struct ref_format *format,
   struct strbuf *final_buf)
 {
@@ -2138,9 +2144,10 @@ void format_ref_array_item(struct ref_array_item *info,
ep = strchr(sp, ')');
if (cp < sp)
append_literal(cp, sp, );
-   get_ref_atom_value(info,
-  parse_ref_filter_atom(format, sp + 2, ep),
-  );
+   if (get_ref_atom_value(info,
+  parse_ref_filter_atom(format, sp + 2, 
ep),
+  ))
+   return -1;
atomv->handler(atomv, );
}
if (*cp) {
@@ -2156,17 +2163,21 @@ void format_ref_array_item(struct ref_array_item *info,
die(_("format: %%(end) atom missing"));
strbuf_addbuf(final_buf, >output);
pop_stack_element();
+   return 0;
 }
 
-void show_ref_array_item(struct ref_array_item *info,
+int show_ref_array_item(struct ref_array_item *info,
 const struct ref_format *format)
 {
struct strbuf final_buf = STRBUF_INIT;
+   int retval = format_ref_array_item(info, format, _buf);
 
-   format_ref_array_item(info, format, _buf);
-   fwrite(final_buf.buf, 1, final_buf.len, stdout);
+   if (!retval) {
+   fwrite(final_buf.buf, 1, final_buf.len, stdout);
+   putchar('\n');
+   }
strbuf_release(_buf);
-   putchar('\n');
+   return retval;
 }
 
 void pretty_print_ref(const char *name, const unsigned char *sha1,
diff --git a/ref-filter.h b/ref-filter.h
index 0d98342b34319..b75c8ac45248e 100644
--- a/ref-filter.h
+++ b/ref-filter.h
@@ -109,12 +109,18 @@ void ref_array_clear(struct ref_array *array);
 int verify_ref_format(struct ref_format *format);
 /*  Sort the given ref_array as per the ref_sorting provided */
 void ref_array_sort(struct ref_sorting *sort, struct ref_array *array);
-/*  Based on the given format and quote_style, fill the strbuf */
-void format_ref_array_item(struct ref_array_item *info,
+/*
+ * Based on the given format and quote_style, fill the strbuf.
+ * Return 0 if everything was successful, -1 otherwise (and strbuf remains 

[PATCH RFC v2 24/25] cat-file: tests for new atoms added

2018-02-05 Thread Olga Telezhnaya
Add some tests for new formatting atoms from ref-filter.
Some of new atoms are supported automatically,
some of them are expanded into empty string
(because they are useless for some types of objects),
some of them could be supported later in other patches.

Signed-off-by: Olga Telezhnaia 
Mentored-by: Christian Couder 
Mentored by: Jeff King 
---
 t/t1006-cat-file.sh | 48 
 1 file changed, 48 insertions(+)

diff --git a/t/t1006-cat-file.sh b/t/t1006-cat-file.sh
index b19f332694620..e72fcaf0e02c5 100755
--- a/t/t1006-cat-file.sh
+++ b/t/t1006-cat-file.sh
@@ -20,6 +20,19 @@ maybe_remove_timestamp () {
 fi
 }
 
+test_atom () {
+name=$1
+sha1=$2
+atoms=$3
+expected=$4
+
+test_expect_success "$name" '
+   echo "$expected" >expect &&
+   echo $sha1 | git cat-file --batch-check="$atoms" >actual &&
+   test_cmp expect actual
+'
+}
+
 run_tests () {
 type=$1
 sha1=$2
@@ -119,6 +132,13 @@ $content"
maybe_remove_timestamp "$(cat actual.full)" $no_ts >actual &&
test_cmp expect actual
 '
+
+for atom in refname parent body trailers upstream push symref flag
+do
+   test_atom "Check %($atom) gives empty output" "$sha1" "%($atom)" ""
+done
+
+test_atom "Check %(HEAD) gives only one space as output" "$sha1" '%(HEAD)' 
' '
 }
 
 hello_content="Hello World"
@@ -140,6 +160,12 @@ test_expect_success '--batch-check without %(rest) 
considers whole line' '
test_cmp expect actual
 '
 
+shortname=`echo $hello_sha1 | sed 's/^.\{0\}\(.\{7\}\).*/\1/'`
+test_atom 'Check format option %(objectname:short) works' "$hello_sha1" 
'%(objectname:short)' "$shortname"
+
+test_atom 'Check format option %(align) is not broken' \
+"$hello_sha1" "%(align:8)%(objecttype)%(end)%(objectname)" "blob
$hello_sha1"
+
 tree_sha1=$(git write-tree)
 tree_size=33
 tree_pretty_content="100644 blob $hello_sha1   hello"
@@ -157,6 +183,17 @@ $commit_message"
 
 run_tests 'commit' $commit_sha1 $commit_size "$commit_content" 
"$commit_content" 1
 
+test_atom "Check format option %(if) is not broken" "$commit_sha1" \
+"%(if)%(author)%(then)%(objectname)%(end)" "$commit_sha1"
+test_atom "Check %(tree) works for commit" "$commit_sha1" "%(tree)" 
"$tree_sha1"
+test_atom "Check %(numparent) works for commit" "$commit_sha1" "%(numparent)" 
"0"
+test_atom "Check %(authorname) works for commit" "$commit_sha1" 
"%(authorname)" "$GIT_AUTHOR_NAME"
+test_atom "Check %(authoremail) works for commit" "$commit_sha1" 
"%(authoremail)" "<$GIT_AUTHOR_EMAIL>"
+test_atom "Check %(committername) works for commit" "$commit_sha1" 
"%(committername)" "$GIT_COMMITTER_NAME"
+test_atom "Check %(committeremail) works for commit" "$commit_sha1" 
"%(committeremail)" "<$GIT_COMMITTER_EMAIL>"
+test_atom "Check %(subject) works for commit" "$commit_sha1" "%(subject)" 
"$commit_message"
+test_atom "Check %(contents) works for commit" "$commit_sha1" "%(contents)" 
"$commit_message"
+
 tag_header_without_timestamp="object $hello_sha1
 type blob
 tag hellotag
@@ -171,6 +208,17 @@ tag_size=$(strlen "$tag_content")
 
 run_tests 'tag' $tag_sha1 $tag_size "$tag_content" "$tag_content" 1
 
+test_atom "Check %(object) works for tag" "$tag_sha1" "%(object)" "$hello_sha1"
+test_atom "Check %(type) works for tag" "$tag_sha1" "%(type)" "blob"
+test_atom "Check %(tag) works for tag" "$tag_sha1" "%(tag)" "hellotag"
+test_atom "Check %(taggername) works for tag" "$tag_sha1" "%(taggername)" 
"$GIT_COMMITTER_NAME"
+test_atom "Check %(taggeremail) works for tag" "$tag_sha1" "%(taggeremail)" 
"<$GIT_COMMITTER_EMAIL>"
+test_atom "Check %(subject) works for tag" "$tag_sha1" "%(subject)" 
"$tag_description"
+test_atom "Check %(contents) works for tag" "$tag_sha1" "%(contents)" 
"$tag_description"
+
+test_atom "Check %(color) gives no additional output" "$sha1" \
+"%(objectname) %(color:green) %(objecttype)" "$sha1  $type"
+
 test_expect_success \
 "Reach a blob from a tag pointing to it" \
 "test '$hello_content' = \"\$(git cat-file blob $tag_sha1)\""

--
https://github.com/git/git/pull/452


[PATCH RFC v2 21/25] ref-filter: unifying formatting of cat-file opts

2018-02-05 Thread Olga Telezhnaya
cat-file options are now filled by general logic.

Signed-off-by: Olga Telezhnaia 
Mentored-by: Christian Couder 
Mentored by: Jeff King 
---
 ref-filter.c | 31 ++-
 1 file changed, 14 insertions(+), 17 deletions(-)

diff --git a/ref-filter.c b/ref-filter.c
index 70c685851466b..aa15dd0b4723e 100644
--- a/ref-filter.c
+++ b/ref-filter.c
@@ -825,8 +825,10 @@ static void grab_common_values(struct atom_value *val, int 
deref, struct object
else if (!strcmp(name, "objectsize")) {
v->value = sz;
v->s = xstrfmt("%lu", sz);
-   }
-   else if (deref)
+   } else if (!strcmp(name, "objectsize:disk")) {
+   v->value = cat_file_info.disk_size;
+   v->s = xstrfmt("%"PRIuMAX, (uintmax_t)v->value);
+   } else if (deref)
grab_objectname(name, obj->oid.hash, v, _atom[i]);
}
 }
@@ -1466,21 +1468,7 @@ static int populate_value(struct ref_array_item *ref)
name++;
}
 
-   if (is_cat) {
-   if (starts_with(name, "objectname"))
-   v->s = oid_to_hex(>oid);
-   else if (starts_with(name, "objecttype"))
-   v->s = typename(ref->type);
-   else if (starts_with(name, "objectsize")) {
-   v->s = xstrfmt("%lu", ref->size);
-   } else if (starts_with(name, "objectsize:disk")) {
-   v->s = xstrfmt("%"PRIuMAX, 
(uintmax_t)ref->disk_size);
-   } else if (starts_with(name, "rest"))
-   v->s = ref->rest;
-   else if (starts_with(name, "deltabase"))
-   v->s = xstrdup(oid_to_hex(ref->delta_base_oid));
-   continue;
-   } else if (starts_with(name, "refname"))
+   if (starts_with(name, "refname"))
refname = get_refname(atom, ref);
else if (starts_with(name, "symref"))
refname = get_symref(atom, ref);
@@ -1536,6 +1524,15 @@ static int populate_value(struct ref_array_item *ref)
else
v->s = " ";
continue;
+   } else if (starts_with(name, "rest")) {
+   v->s = ref->rest ? ref->rest : "";
+   continue;
+   } else if (starts_with(name, "deltabase")) {
+   if (ref->delta_base_oid)
+   v->s = xstrdup(oid_to_hex(ref->delta_base_oid));
+   else
+   v->s = "";
+   continue;
} else if (starts_with(name, "align")) {
v->handler = align_atom_handler;
continue;

--
https://github.com/git/git/pull/452


[PATCH RFC v2 06/25] cat-file: split expand_atom() into 2 functions

2018-02-05 Thread Olga Telezhnaya
Split expand_atom() into 2 different functions,
mark_atom_in_object_info() prepares variable for further filling,
(new) expand_atom() creates resulting string.
Need that for further reusing of formatting logic from ref-filter.
Both functions will be step-by-step removed by the end of this patch.

Signed-off-by: Olga Telezhnaia 
Mentored-by: Christian Couder 
Mentored by: Jeff King 
---
 builtin/cat-file.c | 73 --
 1 file changed, 38 insertions(+), 35 deletions(-)

diff --git a/builtin/cat-file.c b/builtin/cat-file.c
index 37d6096d201b5..edb04a96d9bd3 100644
--- a/builtin/cat-file.c
+++ b/builtin/cat-file.c
@@ -182,47 +182,47 @@ static int is_atom(const char *atom, const char *s, int 
slen)
return alen == slen && !memcmp(atom, s, alen);
 }
 
-static void expand_atom(struct strbuf *sb, const char *atom, int len,
-   void *vdata)
+static void mark_atom_in_object_info(const char *atom, int len,
+struct expand_data *data)
 {
-   struct expand_data *data = vdata;
+   if (is_atom("objectname", atom, len))
+   ; /* do nothing */
+   else if (is_atom("objecttype", atom, len))
+   data->info.typep = >type;
+   else if (is_atom("objectsize", atom, len))
+   data->info.sizep = >size;
+   else if (is_atom("objectsize:disk", atom, len))
+   data->info.disk_sizep = >disk_size;
+   else if (is_atom("rest", atom, len))
+   data->split_on_whitespace = 1;
+   else if (is_atom("deltabase", atom, len))
+   data->info.delta_base_sha1 = data->delta_base_oid.hash;
+   else
+   die("unknown format element: %.*s", len, atom);
+}
 
-   if (is_atom("objectname", atom, len)) {
-   if (!data->mark_query)
-   strbuf_addstr(sb, oid_to_hex(>oid));
-   } else if (is_atom("objecttype", atom, len)) {
-   if (data->mark_query)
-   data->info.typep = >type;
-   else
-   strbuf_addstr(sb, typename(data->type));
-   } else if (is_atom("objectsize", atom, len)) {
-   if (data->mark_query)
-   data->info.sizep = >size;
-   else
-   strbuf_addf(sb, "%lu", data->size);
-   } else if (is_atom("objectsize:disk", atom, len)) {
-   if (data->mark_query)
-   data->info.disk_sizep = >disk_size;
-   else
-   strbuf_addf(sb, "%"PRIuMAX, (uintmax_t)data->disk_size);
-   } else if (is_atom("rest", atom, len)) {
-   if (data->mark_query)
-   data->split_on_whitespace = 1;
-   else if (data->rest)
+static void expand_atom(struct strbuf *sb, const char *atom, int len,
+struct expand_data *data)
+{
+   if (is_atom("objectname", atom, len))
+   strbuf_addstr(sb, oid_to_hex(>oid));
+   else if (is_atom("objecttype", atom, len))
+   strbuf_addstr(sb, typename(data->type));
+   else if (is_atom("objectsize", atom, len))
+   strbuf_addf(sb, "%lu", data->size);
+   else if (is_atom("objectsize:disk", atom, len))
+   strbuf_addf(sb, "%"PRIuMAX, (uintmax_t)data->disk_size);
+   else if (is_atom("rest", atom, len)) {
+   if (data->rest)
strbuf_addstr(sb, data->rest);
-   } else if (is_atom("deltabase", atom, len)) {
-   if (data->mark_query)
-   data->info.delta_base_sha1 = data->delta_base_oid.hash;
-   else
-   strbuf_addstr(sb,
- oid_to_hex(>delta_base_oid));
-   } else
-   die("unknown format element: %.*s", len, atom);
+   } else if (is_atom("deltabase", atom, len))
+   strbuf_addstr(sb, oid_to_hex(>delta_base_oid));
 }
 
-static size_t expand_format(struct strbuf *sb, const char *start, void *data)
+static size_t expand_format(struct strbuf *sb, const char *start, void *vdata)
 {
const char *end;
+   struct expand_data *data = vdata;
 
if (*start != '(')
return 0;
@@ -230,7 +230,10 @@ static size_t expand_format(struct strbuf *sb, const char 
*start, void *data)
if (!end)
die("format element '%s' does not end in ')'", start);
 
-   expand_atom(sb, start + 1, end - start - 1, data);
+   if (data->mark_query)
+   mark_atom_in_object_info(start + 1, end - start - 1, data);
+   else
+   expand_atom(sb, start + 1, end - start - 1, data);
 
return end - start + 1;
 }

--
https://github.com/git/git/pull/452


[PATCH RFC v2 13/25] ref-filter: get rid of mark_atom_in_object_info()

2018-02-05 Thread Olga Telezhnaya
Remove mark_atom_in_object_info() and create same logic
in terms of ref-filter style.

Signed-off-by: Olga Telezhnaia 
Mentored-by: Christian Couder 
Mentored by: Jeff King 
---
 ref-filter.c | 45 +
 1 file changed, 21 insertions(+), 24 deletions(-)

diff --git a/ref-filter.c b/ref-filter.c
index 3f92a27d98b6c..34a54db168265 100644
--- a/ref-filter.c
+++ b/ref-filter.c
@@ -255,13 +255,29 @@ static void objectname_atom_parser(const struct 
ref_format *format, struct used_
 static void objectsize_atom_parser(const struct ref_format *format, struct 
used_atom *atom, const char *arg)
 {
if (!arg)
-   ; /* default to normal object size */
+   cat_file_info->info.sizep = _file_info->size;
else if (!strcmp(arg, "disk"))
cat_file_info->info.disk_sizep = _file_info->disk_size;
else
die(_("urecognized %%(objectsize) argument: %s"), arg);
 }
 
+static void objecttype_atom_parser(const struct ref_format *format, struct 
used_atom *atom, const char *arg)
+{
+   if (!arg)
+   cat_file_info->info.typep = _file_info->type;
+   else
+   die(_("urecognized %%(objecttype) argument: %s"), arg);
+}
+
+static void deltabase_atom_parser(const struct ref_format *format, struct 
used_atom *atom, const char *arg)
+{
+   if (!arg)
+   cat_file_info->info.delta_base_sha1 = 
cat_file_info->delta_base_oid.hash;
+   else
+   die(_("urecognized %%(deltabase) argument: %s"), arg);
+}
+
 static void refname_atom_parser(const struct ref_format *format, struct 
used_atom *atom, const char *arg)
 {
refname_atom_parser_internal(>u.refname, arg, atom->name);
@@ -384,10 +400,10 @@ static struct valid_atom {
 
 static struct valid_atom valid_cat_file_atom[] = {
{ "objectname" },
-   { "objecttype" },
+   { "objecttype", FIELD_STR, objecttype_atom_parser },
{ "objectsize", FIELD_ULONG, objectsize_atom_parser },
{ "rest" },
-   { "deltabase" },
+   { "deltabase", FIELD_STR, deltabase_atom_parser },
 };
 
 #define REF_FORMATTING_STATE_INIT  { 0, NULL }
@@ -411,25 +427,6 @@ struct atom_value {
struct used_atom *atom;
 };
 
-static int is_atom(const char *atom, const char *s, int slen)
-{
-   int alen = strlen(atom);
-   return alen == slen && !memcmp(atom, s, alen);
-}
-
-static void mark_atom_in_object_info(const char *atom, int len,
-   struct expand_data *data)
-{
-   if (is_atom("objecttype", atom, len))
-   data->info.typep = >type;
-   else if (is_atom("objectsize", atom, len))
-   data->info.sizep = >size;
-   else if (is_atom("rest", atom, len))
-   data->split_on_whitespace = 1;
-   else if (is_atom("deltabase", atom, len))
-   data->info.delta_base_sha1 = data->delta_base_oid.hash;
-}
-
 /*
  * Used to parse format string and sort specifiers
  */
@@ -496,8 +493,8 @@ static int parse_ref_filter_atom(const struct ref_format 
*format,
need_tagged = 1;
if (!strcmp(valid_atom[i].name, "symref"))
need_symref = 1;
-   if (cat_file_info)
-   mark_atom_in_object_info(atom, atom_len, cat_file_info);
+   if (cat_file_info && !strcmp(valid_atom[i].name, "rest"))
+   cat_file_info->split_on_whitespace = 1;
return at;
 }
 

--
https://github.com/git/git/pull/452


[PATCH RFC v2 01/25] ref-filter: get rid of goto

2018-02-05 Thread Olga Telezhnaya
Get rid of goto command in ref-filter for better readability.

Signed-off-by: Olga Telezhnaia 
Mentored-by: Christian Couder 
Mentored by: Jeff King 
---
 ref-filter.c | 9 +
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/ref-filter.c b/ref-filter.c
index f9e25aea7a97e..d04295e33448e 100644
--- a/ref-filter.c
+++ b/ref-filter.c
@@ -1477,12 +1477,13 @@ static void populate_value(struct ref_array_item *ref)
 
for (i = 0; i < used_atom_cnt; i++) {
struct atom_value *v = >value[i];
-   if (v->s == NULL)
-   goto need_obj;
+   if (v->s == NULL) {
+   break;
+   }
}
-   return;
+   if (used_atom_cnt <= i)
+   return;
 
- need_obj:
buf = get_obj(>objectname, , , );
if (!buf)
die(_("missing object %s for %s"),

--
https://github.com/git/git/pull/452


[PATCH RFC v2 11/25] ref-filter: rename field in ref_array_item stuct

2018-02-05 Thread Olga Telezhnaya
Rename objectname field to oid in struct ref_array_item.
Next commit will add objectname field that will contain
string representation of object id.

Signed-off-by: Olga Telezhnaia 
Mentored-by: Christian Couder 
Mentored by: Jeff King 
---
 builtin/cat-file.c |  4 ++--
 ref-filter.c   | 10 +-
 ref-filter.h   |  2 +-
 3 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/builtin/cat-file.c b/builtin/cat-file.c
index 61b7acc79155d..367b1bd5802dc 100644
--- a/builtin/cat-file.c
+++ b/builtin/cat-file.c
@@ -186,7 +186,7 @@ static void expand_atom(struct strbuf *sb, const char 
*atom, int len,
 struct ref_array_item *item)
 {
if (is_atom("objectname", atom, len))
-   strbuf_addstr(sb, oid_to_hex(>objectname));
+   strbuf_addstr(sb, oid_to_hex(>oid));
else if (is_atom("objecttype", atom, len))
strbuf_addstr(sb, typename(item->type));
else if (is_atom("objectsize", atom, len))
@@ -294,7 +294,7 @@ static void batch_object_write(const char *obj_name, struct 
batch_options *opt,
return;
}
 
-   item.objectname = data->oid;
+   item.oid = data->oid;
item.type = data->type;
item.size = data->size;
item.disk_size = data->disk_size;
diff --git a/ref-filter.c b/ref-filter.c
index 4acd391b5dfac..d09ec1bde6d54 100644
--- a/ref-filter.c
+++ b/ref-filter.c
@@ -1489,7 +1489,7 @@ int populate_value(struct ref_array_item *ref)
v->s = xstrdup(buf + 1);
}
continue;
-   } else if (!deref && grab_objectname(name, 
ref->objectname.hash, v, atom)) {
+   } else if (!deref && grab_objectname(name, ref->oid.hash, v, 
atom)) {
continue;
} else if (!strcmp(name, "HEAD")) {
if (atom->u.head && !strcmp(ref->refname, atom->u.head))
@@ -1534,13 +1534,13 @@ int populate_value(struct ref_array_item *ref)
if (used_atom_cnt <= i)
return 0;
 
-   buf = get_obj(>objectname, , , );
+   buf = get_obj(>oid, , , );
if (!buf)
die(_("missing object %s for %s"),
-   oid_to_hex(>objectname), ref->refname);
+   oid_to_hex(>oid), ref->refname);
if (!obj)
die(_("parse_object_buffer failed on %s for %s"),
-   oid_to_hex(>objectname), ref->refname);
+   oid_to_hex(>oid), ref->refname);
 
grab_values(ref->value, 0, obj, buf, size);
if (!eaten)
@@ -1890,7 +1890,7 @@ static struct ref_array_item *new_ref_array_item(const 
char *refname,
 {
struct ref_array_item *ref;
FLEX_ALLOC_STR(ref, refname, refname);
-   hashcpy(ref->objectname.hash, objectname);
+   hashcpy(ref->oid.hash, objectname);
ref->flag = flag;
 
return ref;
diff --git a/ref-filter.h b/ref-filter.h
index e16ea2a990119..87b026b8b76d0 100644
--- a/ref-filter.h
+++ b/ref-filter.h
@@ -34,7 +34,7 @@ struct ref_sorting {
 };
 
 struct ref_array_item {
-   struct object_id objectname;
+   struct object_id oid;
int flag;
unsigned int kind;
const char *symref;

--
https://github.com/git/git/pull/452


[PATCH RFC v2 16/25] cat-file: move skip_object_info into ref-filter

2018-02-05 Thread Olga Telezhnaya
Move logic related to skip_object_info into ref-filter,
so that cat-file does not use that field at all.

Signed-off-by: Olga Telezhnaia 
Mentored-by: Christian Couder 
Mentored by: Jeff King 
---
 builtin/cat-file.c | 7 +--
 ref-filter.c   | 5 +
 ref-filter.h   | 1 +
 3 files changed, 7 insertions(+), 6 deletions(-)

diff --git a/builtin/cat-file.c b/builtin/cat-file.c
index a55138f1fd1d1..37adf626d0e55 100644
--- a/builtin/cat-file.c
+++ b/builtin/cat-file.c
@@ -395,14 +395,9 @@ static int batch_objects(struct batch_options *opt)
memset(, 0, sizeof(data));
opt->format.cat_file_data = 
opt->format.is_cat = 1;
+   opt->format.all_objects = opt->all_objects;
verify_ref_format(>format);
 
-   if (opt->all_objects) {
-   struct object_info empty = OBJECT_INFO_INIT;
-   if (!memcmp(, , sizeof(empty)))
-   data.skip_object_info = 1;
-   }
-
/*
 * If we are printing out the object, then always fill in the type,
 * since we will want to decide whether or not to stream.
diff --git a/ref-filter.c b/ref-filter.c
index bbcd507d179a9..7dcd36cd2cddc 100644
--- a/ref-filter.c
+++ b/ref-filter.c
@@ -777,6 +777,11 @@ int verify_ref_format(struct ref_format *format)
}
if (format->need_color_reset_at_eol && !want_color(format->use_color))
format->need_color_reset_at_eol = 0;
+   if (is_cat && format->all_objects) {
+   struct object_info empty = OBJECT_INFO_INIT;
+   if (!memcmp(_file_info->info, , sizeof(empty)))
+   cat_file_info->skip_object_info = 1;
+   }
return 0;
 }
 
diff --git a/ref-filter.h b/ref-filter.h
index f590e5d694df4..e882eb5126118 100644
--- a/ref-filter.h
+++ b/ref-filter.h
@@ -119,6 +119,7 @@ struct ref_format {
 */
struct expand_data *cat_file_data;
int is_cat;
+   int all_objects;
 };
 
 #define REF_FORMAT_INIT { NULL, 0, -1 }

--
https://github.com/git/git/pull/452


[PATCH RFC v2 10/25] ref-filter: make populate_value() global

2018-02-05 Thread Olga Telezhnaya
Make function global for further using in cat-file.
In the end of patch series this function becomes internal again,
so this is a part of middle step. cat-file would use more general
functions further.

Signed-off-by: Olga Telezhnaia 
Mentored-by: Christian Couder 
Mentored by: Jeff King 
---
 ref-filter.c | 2 +-
 ref-filter.h | 3 +++
 2 files changed, 4 insertions(+), 1 deletion(-)

diff --git a/ref-filter.c b/ref-filter.c
index 5c75259b1ab8c..4acd391b5dfac 100644
--- a/ref-filter.c
+++ b/ref-filter.c
@@ -1407,7 +1407,7 @@ static const char *get_refname(struct used_atom *atom, 
struct ref_array_item *re
  * Parse the object referred by ref, and grab needed value.
  * Return 0 if everything was successful, -1 otherwise.
  */
-static int populate_value(struct ref_array_item *ref)
+int populate_value(struct ref_array_item *ref)
 {
void *buf;
struct object *obj;
diff --git a/ref-filter.h b/ref-filter.h
index 781921d4e0978..e16ea2a990119 100644
--- a/ref-filter.h
+++ b/ref-filter.h
@@ -182,4 +182,7 @@ void setup_ref_filter_porcelain_msg(void);
 void pretty_print_ref(const char *name, const unsigned char *sha1,
  const struct ref_format *format);
 
+/* Fill the values of request and prepare all data for final string creation */
+int populate_value(struct ref_array_item *ref);
+
 #endif /*  REF_FILTER_H  */

--
https://github.com/git/git/pull/452


[PATCH v3 08/23] ref-filter: reuse parse_ref_filter_atom()

2018-02-12 Thread Olga Telezhnaya
Continue migrating formatting logic from cat-file to ref-filter.
Reuse parse_ref_filter_atom() for unifying all processes in ref-filter
and further removing of mark_atom_in_object_info().

Signed-off-by: Olga Telezhnaia 
Mentored-by: Christian Couder 
Mentored by: Jeff King 
---
 ref-filter.c | 34 +-
 1 file changed, 25 insertions(+), 9 deletions(-)

diff --git a/ref-filter.c b/ref-filter.c
index ff87e632f463c..5c75259b1ab8c 100644
--- a/ref-filter.c
+++ b/ref-filter.c
@@ -100,6 +100,7 @@ static struct used_atom {
} u;
 } *used_atom;
 static int used_atom_cnt, need_tagged, need_symref;
+struct expand_data *cat_file_info;
 
 static void color_atom_parser(const struct ref_format *format, struct 
used_atom *atom, const char *color_value)
 {
@@ -251,6 +252,16 @@ static void objectname_atom_parser(const struct ref_format 
*format, struct used_
die(_("unrecognized %%(objectname) argument: %s"), arg);
 }
 
+static void objectsize_atom_parser(const struct ref_format *format, struct 
used_atom *atom, const char *arg)
+{
+   if (!arg)
+   ; /* default to normal object size */
+   else if (!strcmp(arg, "disk"))
+   cat_file_info->info.disk_sizep = _file_info->disk_size;
+   else
+   die(_("urecognized %%(objectsize) argument: %s"), arg);
+}
+
 static void refname_atom_parser(const struct ref_format *format, struct 
used_atom *atom, const char *arg)
 {
refname_atom_parser_internal(>u.refname, arg, atom->name);
@@ -371,6 +382,14 @@ static struct valid_atom {
{ "else" },
 };
 
+static struct valid_atom valid_cat_file_atom[] = {
+   { "objectname" },
+   { "objecttype" },
+   { "objectsize", FIELD_ULONG, objectsize_atom_parser },
+   { "rest" },
+   { "deltabase" },
+};
+
 #define REF_FORMATTING_STATE_INIT  { 0, NULL }
 
 struct ref_formatting_stack {
@@ -401,20 +420,14 @@ static int is_atom(const char *atom, const char *s, int 
slen)
 static void mark_atom_in_object_info(const char *atom, int len,
struct expand_data *data)
 {
-   if (is_atom("objectname", atom, len))
-   ; /* do nothing */
-   else if (is_atom("objecttype", atom, len))
+   if (is_atom("objecttype", atom, len))
data->info.typep = >type;
else if (is_atom("objectsize", atom, len))
data->info.sizep = >size;
-   else if (is_atom("objectsize:disk", atom, len))
-   data->info.disk_sizep = >disk_size;
else if (is_atom("rest", atom, len))
data->split_on_whitespace = 1;
else if (is_atom("deltabase", atom, len))
data->info.delta_base_sha1 = data->delta_base_oid.hash;
-   else
-   die("unknown format element: %.*s", len, atom);
 }
 
 /*
@@ -483,6 +496,8 @@ static int parse_ref_filter_atom(const struct ref_format 
*format,
need_tagged = 1;
if (!strcmp(valid_atom[i].name, "symref"))
need_symref = 1;
+   if (cat_file_info)
+   mark_atom_in_object_info(atom, atom_len, cat_file_info);
return at;
 }
 
@@ -726,6 +741,7 @@ int verify_ref_format(struct ref_format *format)
 {
const char *cp, *sp;
 
+   cat_file_info = format->cat_file_data;
format->need_color_reset_at_eol = 0;
for (cp = format->format; *cp && (sp = find_next(cp)); ) {
const char *color, *ep = strchr(sp, ')');
@@ -736,8 +752,8 @@ int verify_ref_format(struct ref_format *format)
/* sp points at "%(" and ep points at the closing ")" */
 
if (format->cat_file_data)
-   mark_atom_in_object_info(sp + 2, ep - sp - 2,
-   format->cat_file_data);
+   at = parse_ref_filter_atom(format, valid_cat_file_atom,
+  
ARRAY_SIZE(valid_cat_file_atom), sp + 2, ep);
else {
at = parse_ref_filter_atom(format, valid_atom,
   ARRAY_SIZE(valid_atom), sp + 
2, ep);

--
https://github.com/git/git/pull/452


[PATCH v3 01/23] ref-filter: get rid of goto

2018-02-12 Thread Olga Telezhnaya
Get rid of goto command in ref-filter for better readability.

Signed-off-by: Olga Telezhnaia 
Mentored-by: Christian Couder 
Mentored by: Jeff King 
---
 ref-filter.c | 9 +
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/ref-filter.c b/ref-filter.c
index f9e25aea7a97e..d04295e33448e 100644
--- a/ref-filter.c
+++ b/ref-filter.c
@@ -1477,12 +1477,13 @@ static void populate_value(struct ref_array_item *ref)
 
for (i = 0; i < used_atom_cnt; i++) {
struct atom_value *v = >value[i];
-   if (v->s == NULL)
-   goto need_obj;
+   if (v->s == NULL) {
+   break;
+   }
}
-   return;
+   if (used_atom_cnt <= i)
+   return;
 
- need_obj:
buf = get_obj(>objectname, , , );
if (!buf)
die(_("missing object %s for %s"),

--
https://github.com/git/git/pull/452


  1   2   >