Use ALLOC_GROW in remote.{c,h}
[gitweb.git] / builtin-reflog.c
index 4c39f1da98e5e690f28f5145a1ab5dba790da68d..4836ec951be727512bcd550dd3604c43c39aa557 100644 (file)
@@ -34,6 +34,16 @@ struct expire_reflog_cb {
        struct cmd_reflog_expire_cb *cmd;
 };
 
+struct collected_reflog {
+       unsigned char sha1[20];
+       char reflog[FLEX_ARRAY];
+};
+struct collect_reflog_cb {
+       struct collected_reflog **e;
+       int alloc;
+       int nr;
+};
+
 #define INCOMPLETE     (1u<<10)
 #define STUDYING       (1u<<11)
 
@@ -249,7 +259,7 @@ static int expire_reflog(const char *ref, const unsigned char *sha1, int unused,
        /* we take the lock for the ref itself to prevent it from
         * getting updated.
         */
-       lock = lock_any_ref_for_update(ref, sha1);
+       lock = lock_any_ref_for_update(ref, sha1, 0);
        if (!lock)
                return error("cannot lock ref '%s'", ref);
        log_file = xstrdup(git_path("logs/%s", ref));
@@ -281,15 +291,35 @@ static int expire_reflog(const char *ref, const unsigned char *sha1, int unused,
        return status;
 }
 
+static int collect_reflog(const char *ref, const unsigned char *sha1, int unused, void *cb_data)
+{
+       struct collected_reflog *e;
+       struct collect_reflog_cb *cb = cb_data;
+       size_t namelen = strlen(ref);
+
+       e = xmalloc(sizeof(*e) + namelen + 1);
+       hashcpy(e->sha1, sha1);
+       memcpy(e->reflog, ref, namelen + 1);
+       ALLOC_GROW(cb->e, cb->nr + 1, cb->alloc);
+       cb->e[cb->nr++] = e;
+       return 0;
+}
+
 static int reflog_expire_config(const char *var, const char *value)
 {
-       if (!strcmp(var, "gc.reflogexpire"))
+       if (!strcmp(var, "gc.reflogexpire")) {
+               if (!value)
+                       config_error_nonbool(var);
                default_reflog_expire = approxidate(value);
-       else if (!strcmp(var, "gc.reflogexpireunreachable"))
+               return 0;
+       }
+       if (!strcmp(var, "gc.reflogexpireunreachable")) {
+               if (!value)
+                       config_error_nonbool(var);
                default_reflog_expire_unreachable = approxidate(value);
-       else
-               return git_default_config(var, value);
-       return 0;
+               return 0;
+       }
+       return git_default_config(var, value);
 }
 
 static int cmd_reflog_expire(int argc, const char **argv, const char *prefix)
@@ -349,8 +379,20 @@ static int cmd_reflog_expire(int argc, const char **argv, const char *prefix)
                        putchar('\n');
        }
 
-       if (do_all)
-               status |= for_each_reflog(expire_reflog, &cb);
+       if (do_all) {
+               struct collect_reflog_cb collected;
+               int i;
+
+               memset(&collected, 0, sizeof(collected));
+               for_each_reflog(collect_reflog, &collected);
+               for (i = 0; i < collected.nr; i++) {
+                       struct collected_reflog *e = collected.e[i];
+                       status |= expire_reflog(e->reflog, e->sha1, 0, &cb);
+                       free(e);
+               }
+               free(collected.e);
+       }
+
        while (i < argc) {
                const char *ref = argv[i++];
                unsigned char sha1[20];