unpack-trees: oneway_merge to update submodules
[gitweb.git] / builtin / describe.c
index 9e9a5ed5d45669605576ceba906cb7a166e3d8d9..3b0b204b1e495626f3490d62f281291ee039ba42 100644 (file)
@@ -3,16 +3,19 @@
 #include "lockfile.h"
 #include "commit.h"
 #include "tag.h"
+#include "blob.h"
 #include "refs.h"
 #include "builtin.h"
 #include "exec_cmd.h"
 #include "parse-options.h"
+#include "revision.h"
 #include "diff.h"
 #include "hashmap.h"
 #include "argv-array.h"
 #include "run-command.h"
+#include "revision.h"
+#include "list-objects.h"
 
-#define SEEN           (1u << 0)
 #define MAX_TAGS       (FLAG_BITS - 1)
 
 static const char * const describe_usage[] = {
@@ -181,7 +184,7 @@ static int get_name(const char *path, const struct object_id *oid, int flag, voi
        }
 
        /* Is it annotated? */
-       if (!peel_ref(path, peeled.hash)) {
+       if (!peel_ref(path, &peeled)) {
                is_annotated = !!oidcmp(oid, &peeled);
        } else {
                oidcpy(&peeled, oid);
@@ -434,6 +437,53 @@ static void describe_commit(struct object_id *oid, struct strbuf *dst)
                strbuf_addstr(dst, suffix);
 }
 
+struct process_commit_data {
+       struct object_id current_commit;
+       struct object_id looking_for;
+       struct strbuf *dst;
+       struct rev_info *revs;
+};
+
+static void process_commit(struct commit *commit, void *data)
+{
+       struct process_commit_data *pcd = data;
+       pcd->current_commit = commit->object.oid;
+}
+
+static void process_object(struct object *obj, const char *path, void *data)
+{
+       struct process_commit_data *pcd = data;
+
+       if (!oidcmp(&pcd->looking_for, &obj->oid) && !pcd->dst->len) {
+               reset_revision_walk();
+               describe_commit(&pcd->current_commit, pcd->dst);
+               strbuf_addf(pcd->dst, ":%s", path);
+               free_commit_list(pcd->revs->commits);
+               pcd->revs->commits = NULL;
+       }
+}
+
+static void describe_blob(struct object_id oid, struct strbuf *dst)
+{
+       struct rev_info revs;
+       struct argv_array args = ARGV_ARRAY_INIT;
+       struct process_commit_data pcd = { null_oid, oid, dst, &revs};
+
+       argv_array_pushl(&args, "internal: The first arg is not parsed",
+               "--objects", "--in-commit-order", "--reverse", "HEAD",
+               NULL);
+
+       init_revisions(&revs, NULL);
+       if (setup_revisions(args.argc, args.argv, &revs, NULL) > 1)
+               BUG("setup_revisions could not handle all args?");
+
+       if (prepare_revision_walk(&revs))
+               die("revision walk setup failed");
+
+       traverse_commit_list(&revs, process_commit, process_object, &pcd);
+       reset_revision_walk();
+}
+
 static void describe(const char *arg, int last_one)
 {
        struct object_id oid;
@@ -445,11 +495,14 @@ static void describe(const char *arg, int last_one)
 
        if (get_oid(arg, &oid))
                die(_("Not a valid object name %s"), arg);
-       cmit = lookup_commit_reference(&oid);
-       if (!cmit)
-               die(_("%s is not a valid '%s' object"), arg, commit_type);
+       cmit = lookup_commit_reference_gently(&oid, 1);
 
-       describe_commit(&oid, &sb);
+       if (cmit)
+               describe_commit(&oid, &sb);
+       else if (lookup_blob(&oid))
+               describe_blob(oid, &sb);
+       else
+               die(_("%s is neither a commit nor blob"), arg);
 
        puts(sb.buf);
 
@@ -557,7 +610,9 @@ int cmd_describe(int argc, const char **argv, const char *prefix)
                        }
                } else if (dirty) {
                        static struct lock_file index_lock;
-                       int fd;
+                       struct rev_info revs;
+                       struct argv_array args = ARGV_ARRAY_INIT;
+                       int fd, result;
 
                        read_cache_preload(NULL);
                        refresh_index(&the_index, REFRESH_QUIET|REFRESH_UNMERGED,
@@ -566,8 +621,13 @@ int cmd_describe(int argc, const char **argv, const char *prefix)
                        if (0 <= fd)
                                update_index_if_able(&the_index, &index_lock);
 
-                       if (!cmd_diff_index(ARRAY_SIZE(diff_index_args) - 1,
-                                           diff_index_args, prefix))
+                       init_revisions(&revs, prefix);
+                       argv_array_pushv(&args, diff_index_args);
+                       if (setup_revisions(args.argc, args.argv, &revs, NULL) != 1)
+                               BUG("malformed internal diff-index command line");
+                       result = run_diff_index(&revs, 0);
+
+                       if (!diff_result_code(&revs.diffopt, result))
                                suffix = NULL;
                        else
                                suffix = dirty;