]> git.ipfire.org Git - thirdparty/git.git/blobdiff - ref-filter.c
ref-filter: add new "describe" atom
[thirdparty/git.git] / ref-filter.c
index 66b8bc586d1c3de2ad020aa7fda1739a5f40001a..8ce72733c82d1c36c6a64058002df27e6951fccb 100644 (file)
@@ -5,6 +5,7 @@
 #include "gpg-interface.h"
 #include "hex.h"
 #include "parse-options.h"
+#include "run-command.h"
 #include "refs.h"
 #include "wildmatch.h"
 #include "object-name.h"
@@ -146,6 +147,7 @@ enum atom_type {
        ATOM_TAGGERDATE,
        ATOM_CREATOR,
        ATOM_CREATORDATE,
+       ATOM_DESCRIBE,
        ATOM_SUBJECT,
        ATOM_BODY,
        ATOM_TRAILERS,
@@ -220,6 +222,7 @@ static struct used_atom {
                        enum { S_BARE, S_GRADE, S_SIGNER, S_KEY,
                               S_FINGERPRINT, S_PRI_KEY_FP, S_TRUST_LEVEL } option;
                } signature;
+               const char **describe_args;
                struct refname_atom refname;
                char *head;
        } u;
@@ -600,6 +603,87 @@ static int contents_atom_parser(struct ref_format *format, struct used_atom *ato
        return 0;
 }
 
+static int describe_atom_option_parser(struct strvec *args, const char **arg,
+                                      struct strbuf *err)
+{
+       const char *argval;
+       size_t arglen = 0;
+       int optval = 0;
+
+       if (match_atom_bool_arg(*arg, "tags", arg, &optval)) {
+               if (!optval)
+                       strvec_push(args, "--no-tags");
+               else
+                       strvec_push(args, "--tags");
+               return 1;
+       }
+
+       if (match_atom_arg_value(*arg, "abbrev", arg, &argval, &arglen)) {
+               char *endptr;
+
+               if (!arglen)
+                       return strbuf_addf_ret(err, -1,
+                                              _("argument expected for %s"),
+                                              "describe:abbrev");
+               if (strtol(argval, &endptr, 10) < 0)
+                       return strbuf_addf_ret(err, -1,
+                                              _("positive value expected %s=%s"),
+                                              "describe:abbrev", argval);
+               if (endptr - argval != arglen)
+                       return strbuf_addf_ret(err, -1,
+                                              _("cannot fully parse %s=%s"),
+                                              "describe:abbrev", argval);
+
+               strvec_pushf(args, "--abbrev=%.*s", (int)arglen, argval);
+               return 1;
+       }
+
+       if (match_atom_arg_value(*arg, "match", arg, &argval, &arglen)) {
+               if (!arglen)
+                       return strbuf_addf_ret(err, -1,
+                                              _("value expected %s="),
+                                              "describe:match");
+
+               strvec_pushf(args, "--match=%.*s", (int)arglen, argval);
+               return 1;
+       }
+
+       if (match_atom_arg_value(*arg, "exclude", arg, &argval, &arglen)) {
+               if (!arglen)
+                       return strbuf_addf_ret(err, -1,
+                                              _("value expected %s="),
+                                              "describe:exclude");
+
+               strvec_pushf(args, "--exclude=%.*s", (int)arglen, argval);
+               return 1;
+       }
+
+       return 0;
+}
+
+static int describe_atom_parser(struct ref_format *format UNUSED,
+                               struct used_atom *atom,
+                               const char *arg, struct strbuf *err)
+{
+       struct strvec args = STRVEC_INIT;
+
+       for (;;) {
+               int found = 0;
+               const char *bad_arg = arg;
+
+               if (!arg || !*arg)
+                       break;
+
+               found = describe_atom_option_parser(&args, &arg, err);
+               if (found < 0)
+                       return found;
+               if (!found)
+                       return err_bad_arg(err, "describe", bad_arg);
+       }
+       atom->u.describe_args = strvec_detach(&args);
+       return 0;
+}
+
 static int raw_atom_parser(struct ref_format *format UNUSED,
                           struct used_atom *atom,
                           const char *arg, struct strbuf *err)
@@ -802,6 +886,7 @@ static struct {
        [ATOM_TAGGERDATE] = { "taggerdate", SOURCE_OBJ, FIELD_TIME },
        [ATOM_CREATOR] = { "creator", SOURCE_OBJ },
        [ATOM_CREATORDATE] = { "creatordate", SOURCE_OBJ, FIELD_TIME },
+       [ATOM_DESCRIBE] = { "describe", SOURCE_OBJ, FIELD_STR, describe_atom_parser },
        [ATOM_SUBJECT] = { "subject", SOURCE_OBJ, FIELD_STR, subject_atom_parser },
        [ATOM_BODY] = { "body", SOURCE_OBJ, FIELD_STR, body_atom_parser },
        [ATOM_TRAILERS] = { "trailers", SOURCE_OBJ, FIELD_STR, trailers_atom_parser },
@@ -1708,6 +1793,44 @@ static void append_lines(struct strbuf *out, const char *buf, unsigned long size
        }
 }
 
+static void grab_describe_values(struct atom_value *val, int deref,
+                                struct object *obj)
+{
+       struct commit *commit = (struct commit *)obj;
+       int i;
+
+       for (i = 0; i < used_atom_cnt; i++) {
+               struct used_atom *atom = &used_atom[i];
+               enum atom_type type = atom->atom_type;
+               const char *name = atom->name;
+               struct atom_value *v = &val[i];
+
+               struct child_process cmd = CHILD_PROCESS_INIT;
+               struct strbuf out = STRBUF_INIT;
+               struct strbuf err = STRBUF_INIT;
+
+               if (type != ATOM_DESCRIBE)
+                       continue;
+
+               if (!!deref != (*name == '*'))
+                       continue;
+
+               cmd.git_cmd = 1;
+               strvec_push(&cmd.args, "describe");
+               strvec_pushv(&cmd.args, atom->u.describe_args);
+               strvec_push(&cmd.args, oid_to_hex(&commit->object.oid));
+               if (pipe_command(&cmd, NULL, 0, &out, 0, &err, 0) < 0) {
+                       error(_("failed to run 'describe'"));
+                       v->s = xstrdup("");
+                       continue;
+               }
+               strbuf_rtrim(&out);
+               v->s = strbuf_detach(&out, NULL);
+
+               strbuf_release(&err);
+       }
+}
+
 /* See grab_values */
 static void grab_sub_body_contents(struct atom_value *val, int deref, struct expand_data *data)
 {
@@ -1817,6 +1940,7 @@ static void grab_values(struct atom_value *val, int deref, struct object *obj, s
                grab_tag_values(val, deref, obj);
                grab_sub_body_contents(val, deref, data);
                grab_person("tagger", val, deref, buf);
+               grab_describe_values(val, deref, obj);
                break;
        case OBJ_COMMIT:
                grab_commit_values(val, deref, obj);
@@ -1824,6 +1948,7 @@ static void grab_values(struct atom_value *val, int deref, struct object *obj, s
                grab_person("author", val, deref, buf);
                grab_person("committer", val, deref, buf);
                grab_signature(val, deref, obj);
+               grab_describe_values(val, deref, obj);
                break;
        case OBJ_TREE:
                /* grab_tree_values(val, deref, obj, buf, sz); */