#include "tree.h"
#include "blob.h"
#include "quote.h"
-#include <fnmatch.h>
/* Quoting styles */
#define QUOTE_NONE 0
#define QUOTE_SHELL 1
#define QUOTE_PERL 2
#define QUOTE_PYTHON 3
+#define QUOTE_TCL 4
typedef enum { FIELD_STR, FIELD_ULONG, FIELD_TIME } cmp_type;
{ "taggername" },
{ "taggeremail" },
{ "taggerdate", FIELD_TIME },
+ { "creator" },
+ { "creatordate", FIELD_TIME },
{ "subject" },
{ "body" },
{ "contents" },
while (*cp) {
if (*cp == '%') {
/* %( is the start of an atom;
- * %% is a quoteed per-cent.
+ * %% is a quoted per-cent.
*/
if (cp[1] == '(')
return cp;
*/
static void *get_obj(const unsigned char *sha1, struct object **obj, unsigned long *sz, int *eaten)
{
- char type[20];
- void *buf = read_sha1_file(sha1, type, sz);
+ enum object_type type;
+ void *buf = read_sha1_file(sha1, &type, sz);
if (buf)
*obj = parse_object_buffer(sha1, type, *sz, buf, eaten);
if (deref)
name++;
if (!strcmp(name, "objecttype"))
- v->s = type_names[obj->type];
+ v->s = typename(obj->type);
else if (!strcmp(name, "objectsize")) {
char *s = xmalloc(40);
sprintf(s, "%lu", sz);
return "";
}
-static char *copy_line(const char *buf)
+static const char *copy_line(const char *buf)
{
const char *eol = strchr(buf, '\n');
char *line;
return line;
}
-static char *copy_name(const char *buf)
+static const char *copy_name(const char *buf)
{
const char *eol = strchr(buf, '\n');
const char *eoname = strstr(buf, " <");
return line;
}
-static char *copy_email(const char *buf)
+static const char *copy_email(const char *buf)
{
const char *email = strchr(buf, '<');
const char *eoemail = strchr(email, '>');
else if (!strcmp(name + wholen, "date"))
grab_date(wholine, v);
}
+
+ /* For a tag or a commit object, if "creator" or "creatordate" is
+ * requested, do something special.
+ */
+ if (strcmp(who, "tagger") && strcmp(who, "committer"))
+ return; /* "author" for commit object is not wanted */
+ if (!wholine)
+ wholine = find_wholine(who, wholen, buf, sz);
+ if (!wholine)
+ return;
+ for (i = 0; i < used_atom_cnt; i++) {
+ const char *name = used_atom[i];
+ struct atom_value *v = &val[i];
+ if (!!deref != (*name == '*'))
+ continue;
+ if (deref)
+ name++;
+
+ if (!strcmp(name, "creatordate"))
+ grab_date(wholine, v);
+ else if (!strcmp(name, "creator"))
+ v->s = copy_line(wholine);
+ }
}
static void find_subpos(const char *buf, unsigned long sz, const char **sub, const char **body)
if (!strcmp(name, "subject"))
v->s = copy_line(subpos);
else if (!strcmp(name, "body"))
- v->s = bodypos;
+ v->s = xstrdup(bodypos);
else if (!strcmp(name, "contents"))
- v->s = subpos;
+ v->s = xstrdup(subpos);
}
}
*v = &ref->value[atom];
}
-static struct refinfo **grab_array;
-static const char **grab_pattern;
-static int *grab_cnt;
+struct grab_ref_cbdata {
+ struct refinfo **grab_array;
+ const char **grab_pattern;
+ int grab_cnt;
+};
/*
* A call-back given to for_each_ref(). It is unfortunate that we
* need to use global variables to pass extra information to this
* function.
*/
-static int grab_single_ref(const char *refname, const unsigned char *sha1)
+static int grab_single_ref(const char *refname, const unsigned char *sha1, int flag, void *cb_data)
{
+ struct grab_ref_cbdata *cb = cb_data;
struct refinfo *ref;
int cnt;
- if (*grab_pattern) {
+ if (*cb->grab_pattern) {
const char **pattern;
int namelen = strlen(refname);
- for (pattern = grab_pattern; *pattern; pattern++) {
+ for (pattern = cb->grab_pattern; *pattern; pattern++) {
const char *p = *pattern;
int plen = strlen(p);
ref->refname = xstrdup(refname);
hashcpy(ref->objectname, sha1);
- cnt = *grab_cnt;
- grab_array = xrealloc(grab_array, sizeof(*grab_array) * (cnt + 1));
- grab_array[cnt++] = ref;
- *grab_cnt = cnt;
+ cnt = cb->grab_cnt;
+ cb->grab_array = xrealloc(cb->grab_array,
+ sizeof(*cb->grab_array) * (cnt + 1));
+ cb->grab_array[cnt++] = ref;
+ cb->grab_cnt = cnt;
return 0;
}
-static struct refinfo **grab_refs(const char **pattern, int *cnt)
-{
- /* Sheesh, we really should make for-each-ref to take
- * callback data.
- */
- *cnt = 0;
- grab_pattern = pattern;
- grab_cnt = cnt;
- for_each_ref(grab_single_ref);
- return grab_array;
-}
-
static int cmp_ref_sort(struct ref_sort *s, struct refinfo *a, struct refinfo *b)
{
struct atom_value *va, *vb;
case QUOTE_PYTHON:
python_quote_print(stdout, v->s);
break;
+ case QUOTE_TCL:
+ tcl_quote_print(stdout, v->s);
+ break;
}
}
int maxcount = 0;
int quote_style = -1; /* unspecified yet */
struct refinfo **refs;
+ struct grab_ref_cbdata cbdata;
for (i = 1; i < ac; i++) {
const char *arg = av[i];
i++;
break;
}
- if (!strncmp(arg, "--format=", 9)) {
+ if (!prefixcmp(arg, "--format=")) {
if (format)
die("more than one --format?");
format = arg + 9;
quote_style = QUOTE_PYTHON;
continue;
}
- if (!strncmp(arg, "--count=", 8)) {
+ if (!strcmp(arg, "--tcl") ) {
+ if (0 <= quote_style)
+ die("more than one quoting style?");
+ quote_style = QUOTE_TCL;
+ continue;
+ }
+ if (!prefixcmp(arg, "--count=")) {
if (maxcount)
die("more than one --count?");
maxcount = atoi(arg + 8);
die("The number %s did not parse", arg);
continue;
}
- if (!strncmp(arg, "--sort=", 7)) {
+ if (!prefixcmp(arg, "--sort=")) {
struct ref_sort *s = xcalloc(1, sizeof(*s));
int len;
verify_format(format);
- refs = grab_refs(av + i, &num_refs);
+ memset(&cbdata, 0, sizeof(cbdata));
+ cbdata.grab_pattern = av + i;
+ for_each_ref(grab_single_ref, &cbdata);
+ refs = cbdata.grab_array;
+ num_refs = cbdata.grab_cnt;
for (i = 0; i < used_atom_cnt; i++) {
if (used_atom[i][0] == '*') {