Commit Diff


commit - c560c1f52d2adb8966e2f783ed7d3f0b37117df9
commit + b8af7c0693fbaccaecf7b904aaf237066269f222
blob - d595de198f4880c3458bb395b994e889acf68df3
blob + 220102239d910b5a63c4c94a6a0c3a0152192ef0
--- got/got.c
+++ got/got.c
@@ -7855,9 +7855,32 @@ usage_send(void)
 	exit(1);
 }
 
+static void
+print_load_info(int print_colored, int print_found, int print_trees,
+    int ncolored, int nfound, int ntrees)
+{
+	if (print_colored) {
+		printf("%d commit%s colored", ncolored,
+		    ncolored == 1 ? "" : "s");
+	}
+	if (print_found) {
+		printf("%s%d object%s found",
+		    ncolored > 0 ? "; " : "",
+		    nfound, nfound == 1 ? "" : "s");
+	}
+	if (print_trees) {
+		printf("; %d tree%s scanned", ntrees,
+		    ntrees == 1 ? "" : "s");
+	}
+}
+
 struct got_send_progress_arg {
 	char last_scaled_packsize[FMT_SCALED_STRSIZE];
 	int verbosity;
+	int last_ncolored;
+	int last_nfound;
+	int last_ntrees;
+	int loading_done;
 	int last_ncommits;
 	int last_nobj_total;
 	int last_p_deltify;
@@ -7869,14 +7892,15 @@ struct got_send_progress_arg {
 };
 
 static const struct got_error *
-send_progress(void *arg, off_t packfile_size, int ncommits, int nobj_total,
-    int nobj_deltify, int nobj_written, off_t bytes_sent, const char *refname,
-    int success)
+send_progress(void *arg, int ncolored, int nfound, int ntrees,
+    off_t packfile_size, int ncommits, int nobj_total, int nobj_deltify,
+    int nobj_written, off_t bytes_sent, const char *refname, int success)
 {
 	struct got_send_progress_arg *a = arg;
 	char scaled_packsize[FMT_SCALED_STRSIZE];
 	char scaled_sent[FMT_SCALED_STRSIZE];
 	int p_deltify = 0, p_written = 0, p_sent = 0;
+	int print_colored = 0, print_found = 0, print_trees = 0;
 	int print_searching = 0, print_total = 0;
 	int print_deltify = 0, print_written = 0, print_sent = 0;
 
@@ -7906,6 +7930,39 @@ send_progress(void *arg, off_t packfile_size, int ncom
 		return NULL;
 	}
 
+	if (a->last_ncolored != ncolored) {
+		print_colored = 1;
+		a->last_ncolored = ncolored;
+	}
+
+	if (a->last_nfound != nfound) {
+		print_colored = 1;
+		print_found = 1;
+		a->last_nfound = nfound;
+	}
+
+	if (a->last_ntrees != ntrees) {
+		print_colored = 1;
+		print_found = 1;
+		print_trees = 1;
+		a->last_ntrees = ntrees;
+	}
+
+	if ((print_colored || print_found || print_trees) &&
+	    !a->loading_done) {
+		printf("\r");
+		print_load_info(print_colored, print_found, print_trees,
+		    ncolored, nfound, ntrees);
+		a->printed_something = 1;
+		fflush(stdout);
+		return NULL;
+	} else if (!a->loading_done) {
+		printf("\r");
+		print_load_info(1, 1, 1, ncolored, nfound, ntrees);
+		printf("\n");
+		a->loading_done = 1;
+	}
+
 	if (fmt_scaled(packfile_size, scaled_packsize) == -1)
 		return got_error_from_errno("fmt_scaled");
 	if (fmt_scaled(bytes_sent, scaled_sent) == -1)
blob - bd7343dcca754f398aaba30df74ecd27b90d2ee7
blob + 09d1ca1db98e99e774fa86e99f0212c6871c7fcb
--- gotadmin/gotadmin.c
+++ gotadmin/gotadmin.c
@@ -381,6 +381,10 @@ usage_pack(void)
 
 struct got_pack_progress_arg {
 	char last_scaled_size[FMT_SCALED_STRSIZE];
+	int last_ncolored;
+	int last_nfound;
+	int last_ntrees;
+	int loading_done;
 	int last_ncommits;
 	int last_nobj_total;
 	int last_p_deltify;
@@ -391,18 +395,72 @@ struct got_pack_progress_arg {
 	int printed_something;
 };
 
+static void
+print_load_info(int print_colored, int print_found, int print_trees,
+    int ncolored, int nfound, int ntrees)
+{
+	if (print_colored) {
+		printf("%d commit%s colored", ncolored,
+		    ncolored == 1 ? "" : "s");
+	}
+	if (print_found) {
+		printf("%s%d object%s found",
+		    ncolored > 0 ? "; " : "",
+		    nfound, nfound == 1 ? "" : "s");
+	}
+	if (print_trees) {
+		printf("; %d tree%s scanned", ntrees,
+		    ntrees == 1 ? "" : "s");
+	}
+}
+
 static const struct got_error *
-pack_progress(void *arg, off_t packfile_size, int ncommits,
-    int nobj_total, int nobj_deltify, int nobj_written)
+pack_progress(void *arg, int ncolored, int nfound, int ntrees,
+    off_t packfile_size, int ncommits, int nobj_total, int nobj_deltify,
+    int nobj_written)
 {
 	struct got_pack_progress_arg *a = arg;
 	char scaled_size[FMT_SCALED_STRSIZE];
 	int p_deltify, p_written;
+	int print_colored = 0, print_found = 0, print_trees = 0;
 	int print_searching = 0, print_total = 0;
 	int print_deltify = 0, print_written = 0;
 
 	if (a->verbosity < 0)
+		return NULL;
+
+	if (a->last_ncolored != ncolored) {
+		print_colored = 1;
+		a->last_ncolored = ncolored;
+	}
+
+	if (a->last_nfound != nfound) {
+		print_colored = 1;
+		print_found = 1;
+		a->last_nfound = nfound;
+	}
+
+	if (a->last_ntrees != ntrees) {
+		print_colored = 1;
+		print_found = 1;
+		print_trees = 1;
+		a->last_ntrees = ntrees;
+	}
+
+	if ((print_colored || print_found || print_trees) &&
+	    !a->loading_done) {
+		printf("\r");
+		print_load_info(print_colored, print_found, print_trees,
+		    ncolored, nfound, ntrees);
+		a->printed_something = 1;
+		fflush(stdout);
 		return NULL;
+	} else if (!a->loading_done) {
+		printf("\r");
+		print_load_info(1, 1, 1, ncolored, nfound, ntrees);
+		printf("\n");
+		a->loading_done = 1;
+	}
 
 	if (fmt_scaled(packfile_size, scaled_size) == -1)
 		return got_error_from_errno("fmt_scaled");
blob - 8bc7ea591673f80b94917ac36991936b0fc46038
blob + 2caf2a94d4ed262a215863f07c9e967a8f052cc3
--- include/got_repository_admin.h
+++ include/got_repository_admin.h
@@ -16,8 +16,8 @@
 
 /* A callback function which gets invoked with progress information to print. */
 typedef const struct got_error *(*got_pack_progress_cb)(void *arg,
-    off_t packfile_size, int ncommits, int nobj_total, int obj_deltify,
-    int nobj_written);
+    int ncolored, int nfound, int ntrees, off_t packfile_size, int ncommits,
+    int nobj_total, int obj_deltify, int nobj_written);
 
 /*
  * Attempt to pack objects reachable via 'include_refs' into a new packfile.
blob - 225bc42faab244492a77e967c829b9cf47301009
blob + 19e9e4f116e70c354ec4bbff8ce7e5a1615acd1f
--- include/got_send.h
+++ include/got_send.h
@@ -36,8 +36,8 @@ const struct got_error *got_send_connect(pid_t *, int 
 
 /* A callback function which gets invoked with progress information to print. */
 typedef const struct got_error *(*got_send_progress_cb)(void *,
-    off_t packfile_size, int ncommits, int nobj_total,
-    int nobj_deltify, int nobj_written, off_t bytes_sent,
+    int ncolored, int nfound, int ntrees, off_t packfile_size, int ncommits,
+    int nobj_total, int nobj_deltify, int nobj_written, off_t bytes_sent,
     const char *refname, int success);
 
 /*
blob - 5a375985f96945d5f42e1d0b1b1f051e5df5c329
blob + 273f38d8a8d75455bcb4a4eebf66c1d7dae0df8e
--- lib/pack_create.c
+++ lib/pack_create.c
@@ -408,8 +408,9 @@ encode_delta(struct got_pack_meta *m, struct got_raw_o
 
 static const struct got_error *
 report_progress(got_pack_progress_cb progress_cb, void *progress_arg,
-    struct got_ratelimit *rl, off_t packfile_size, int ncommits,
-    int nobj_total, int obj_deltify, int nobj_written)
+    struct got_ratelimit *rl, int ncolored, int nfound, int ntrees,
+    off_t packfile_size, int ncommits, int nobj_total, int obj_deltify,
+    int nobj_written)
 {
 	const struct got_error *err;
 	int elapsed;
@@ -421,8 +422,8 @@ report_progress(got_pack_progress_cb progress_cb, void
 	if (err || !elapsed)
 		return err;
 
-	return progress_cb(progress_arg, packfile_size, ncommits,
-	    nobj_total, obj_deltify, nobj_written);
+	return progress_cb(progress_arg, ncolored, nfound, ntrees,
+	    packfile_size, ncommits, nobj_total, obj_deltify, nobj_written);
 }
 
 static const struct got_error *
@@ -531,6 +532,9 @@ struct search_deltas_arg {
 	struct got_ratelimit *rl;
 	got_cancel_cb cancel_cb;
 	void *cancel_arg;
+	int ncolored;
+	int nfound;
+	int ntrees;
 	int ncommits;
 };
 
@@ -576,8 +580,8 @@ search_delta_for_object(struct got_object_id *id, void
 		if (err)
 			goto done;
 		err = report_progress(a->progress_cb, a->progress_arg, a->rl,
-		    0L, a->ncommits, got_object_idset_num_elements(a->idset),
-		    a->v->nmeta, 0);
+		    a->ncolored, a->nfound, a->ntrees, 0L, a->ncommits,
+		    got_object_idset_num_elements(a->idset), a->v->nmeta, 0);
 	}
 done:
 	got_object_close(obj);
@@ -586,7 +590,8 @@ done:
 
 static const struct got_error *
 search_deltas(struct got_pack_metavec *v, struct got_object_idset *idset,
-    int delta_cache_fd, int ncommits, struct got_repository *repo,
+    int delta_cache_fd, int ncolored, int nfound, int ntrees, int ncommits,
+    struct got_repository *repo,
     got_pack_progress_cb progress_cb, void *progress_arg,
     struct got_ratelimit *rl, got_cancel_cb cancel_cb, void *cancel_arg)
 {
@@ -626,6 +631,9 @@ search_deltas(struct got_pack_metavec *v, struct got_o
 	sda.rl = rl;
 	sda.cancel_cb = cancel_cb;
 	sda.cancel_arg = cancel_arg;
+	sda.ncolored = ncolored;
+	sda.nfound = nfound;
+	sda.ntrees = ntrees;
 	sda.ncommits = ncommits;
 	err = got_object_idset_for_each(idset, search_delta_for_object, &sda);
 done:
@@ -634,8 +642,9 @@ done:
 }
 
 static const struct got_error *
-pick_deltas(struct got_pack_meta **meta, int nmeta, int ncommits,
-    int nreused, FILE *delta_cache, struct got_repository *repo,
+pick_deltas(struct got_pack_meta **meta, int nmeta, int ncolored,
+    int nfound, int ntrees, int ncommits, int nreused, FILE *delta_cache,
+    struct got_repository *repo,
     got_pack_progress_cb progress_cb, void *progress_arg,
     struct got_ratelimit *rl, got_cancel_cb cancel_cb, void *cancel_arg)
 {
@@ -658,7 +667,8 @@ pick_deltas(struct got_pack_meta **meta, int nmeta, in
 				break;
 		}
 		err = report_progress(progress_cb, progress_arg, rl,
-		    0L, ncommits, nreused + nmeta, nreused + i, 0);
+		    ncolored, nfound, ntrees, 0L, ncommits, nreused + nmeta,
+		    nreused + i, 0);
 		if (err)
 			goto done;
 		m = meta[i];
@@ -868,7 +878,9 @@ static const struct got_error *
 load_tree_entries(struct got_object_id_queue *ids, int want_meta,
     struct got_object_idset *idset, struct got_object_id *tree_id,
     const char *dpath, time_t mtime, struct got_repository *repo,
-    int loose_obj_only, got_cancel_cb cancel_cb, void *cancel_arg)
+    int loose_obj_only, int *ncolored, int *nfound, int *ntrees,
+    got_pack_progress_cb progress_cb, void *progress_arg,
+    struct got_ratelimit *rl, got_cancel_cb cancel_cb, void *cancel_arg)
 {
 	const struct got_error *err;
 	struct got_tree_object *tree;
@@ -876,6 +888,12 @@ load_tree_entries(struct got_object_id_queue *ids, int
 	int i;
 
 	err = got_object_open_as_tree(&tree, repo, tree_id);
+	if (err)
+		return err;
+
+	(*ntrees)++;
+	err = report_progress(progress_cb, progress_arg, rl,
+	    *ncolored, *nfound, *ntrees, 0L, 0, 0, 0, 0);
 	if (err)
 		return err;
 
@@ -911,6 +929,11 @@ load_tree_entries(struct got_object_id_queue *ids, int
 			    GOT_OBJ_TYPE_BLOB, mtime, loose_obj_only, repo);
 			if (err)
 				break;
+			(*nfound)++;
+			err = report_progress(progress_cb, progress_arg, rl,
+			    *ncolored, *nfound, *ntrees, 0L, 0, 0, 0, 0);
+			if (err)
+				break;
 		}
 		free(p);
 		p = NULL;
@@ -924,8 +947,10 @@ load_tree_entries(struct got_object_id_queue *ids, int
 static const struct got_error *
 load_tree(int want_meta, struct got_object_idset *idset,
     struct got_object_id *tree_id, const char *dpath, time_t mtime,
-    int loose_obj_only, struct got_repository *repo,
-    got_cancel_cb cancel_cb, void *cancel_arg)
+    struct got_repository *repo, int loose_obj_only,
+    int *ncolored, int *nfound, int *ntrees,
+    got_pack_progress_cb progress_cb, void *progress_arg,
+    struct got_ratelimit *rl, got_cancel_cb cancel_cb, void *cancel_arg)
 {
 	const struct got_error *err = NULL;
 	struct got_object_id_queue tree_ids;
@@ -963,8 +988,16 @@ load_tree(int want_meta, struct got_object_idset *idse
 			break;
 		}
 
+		(*nfound)++;
+		err = report_progress(progress_cb, progress_arg, rl,
+		    *ncolored, *nfound, *ntrees, 0L, 0, 0, 0, 0);
+		if (err)
+			break;
+
 		err = load_tree_entries(&tree_ids, want_meta, idset, qid->id,
-		    dpath, mtime, repo, loose_obj_only, cancel_cb, cancel_arg);
+		    dpath, mtime, repo, loose_obj_only, ncolored, nfound,
+		    ntrees, progress_cb, progress_arg, rl,
+		    cancel_cb, cancel_arg);
 		got_object_qid_free(qid);
 		if (err)
 			break;
@@ -977,7 +1010,9 @@ load_tree(int want_meta, struct got_object_idset *idse
 static const struct got_error *
 load_commit(int want_meta, struct got_object_idset *idset,
     struct got_object_id *id, struct got_repository *repo, int loose_obj_only,
-    got_cancel_cb cancel_cb, void *cancel_arg)
+    int *ncolored, int *nfound, int *ntrees,
+    got_pack_progress_cb progress_cb, void *progress_arg,
+    struct got_ratelimit *rl, got_cancel_cb cancel_cb, void *cancel_arg)
 {
 	const struct got_error *err;
 	struct got_commit_object *commit;
@@ -1004,9 +1039,16 @@ load_commit(int want_meta, struct got_object_idset *id
 	if (err)
 		goto done;
 
+	(*nfound)++;
+	err = report_progress(progress_cb, progress_arg, rl,
+	    *ncolored, *nfound, *ntrees, 0L, 0, 0, 0, 0);
+	if (err)
+		goto done;
+
 	err = load_tree(want_meta, idset, got_object_commit_get_tree_id(commit),
 	    "", got_object_commit_get_committer_time(commit),
-	    loose_obj_only, repo, cancel_cb, cancel_arg);
+	    repo, loose_obj_only, ncolored, nfound, ntrees,
+	    progress_cb, progress_arg, rl, cancel_cb, cancel_arg);
 done:
 	got_object_commit_close(commit);
 	return err;
@@ -1015,7 +1057,9 @@ done:
 static const struct got_error *
 load_tag(int want_meta, struct got_object_idset *idset,
     struct got_object_id *id, struct got_repository *repo, int loose_obj_only,
-    got_cancel_cb cancel_cb, void *cancel_arg)
+    int *ncolored, int *nfound, int *ntrees,
+    got_pack_progress_cb progress_cb, void *progress_arg,
+    struct got_ratelimit *rl, got_cancel_cb cancel_cb, void *cancel_arg)
 {
 	const struct got_error *err;
 	struct got_tag_object *tag = NULL;
@@ -1042,17 +1086,25 @@ load_tag(int want_meta, struct got_object_idset *idset
 	if (err)
 		goto done;
 
+	(*nfound)++;
+	err = report_progress(progress_cb, progress_arg, rl,
+	    *ncolored, *nfound, *ntrees, 0L, 0, 0, 0, 0);
+	if (err)
+		goto done;
+
 	switch (got_object_tag_get_object_type(tag)) {
 	case GOT_OBJ_TYPE_COMMIT:
 		err = load_commit(want_meta, idset,
-		    got_object_tag_get_object_id(tag), repo,
-		    loose_obj_only, cancel_cb, cancel_arg);
+		    got_object_tag_get_object_id(tag), repo, loose_obj_only,
+		    ncolored, nfound, ntrees, progress_cb, progress_arg, rl,
+		    cancel_cb, cancel_arg);
 		break;
 	case GOT_OBJ_TYPE_TREE:
 		err = load_tree(want_meta, idset,
 		    got_object_tag_get_object_id(tag), "",
-		    got_object_tag_get_tagger_time(tag),
-		    loose_obj_only, repo, cancel_cb, cancel_arg);
+		    got_object_tag_get_tagger_time(tag), repo, loose_obj_only,
+		    ncolored, nfound, ntrees, progress_cb, progress_arg, rl,
+		    cancel_cb, cancel_arg);
 		break;
 	default:
 		break;
@@ -1174,11 +1226,12 @@ append_id(struct got_object_id *id, void *data, void *
 }
 
 static const struct got_error *
-findtwixt(struct got_object_id ***res, int *nres,
+findtwixt(struct got_object_id ***res, int *nres, int *ncolored,
     struct got_object_id **head, int nhead,
     struct got_object_id **tail, int ntail,
     struct got_repository *repo,
-    got_cancel_cb cancel_cb, void *cancel_arg)
+    got_pack_progress_cb progress_cb, void *progress_arg,
+    struct got_ratelimit *rl, got_cancel_cb cancel_cb, void *cancel_arg)
 {
 	const struct got_error *err = NULL;
 	struct got_object_id_queue ids;
@@ -1189,6 +1242,7 @@ findtwixt(struct got_object_id ***res, int *nres,
 	STAILQ_INIT(&ids);
 	*res = NULL;
 	*nres = 0;
+	*ncolored = 0;
 
 	keep = got_object_idset_alloc();
 	if (keep == NULL)
@@ -1238,6 +1292,12 @@ findtwixt(struct got_object_id ***res, int *nres,
 			ncolor = COLOR_KEEP;
 		else
 			ncolor = COLOR_BLANK;
+
+		(*ncolored)++;
+		err = report_progress(progress_cb, progress_arg, rl,
+		    *ncolored, 0, 0, 0L, 0, 0, 0, 0);
+		if (err)
+			goto done;
 
 		if (ncolor == COLOR_DROP || (ncolor == COLOR_KEEP &&
 		    qcolor == COLOR_KEEP)) {
@@ -1327,17 +1387,22 @@ done:
 }
 
 static const struct got_error *
-load_object_ids(struct got_object_idset *idset,
-    struct got_object_id **theirs, int ntheirs,
+load_object_ids(int *ncolored, int *nfound, int *ntrees,
+    struct got_object_idset *idset, struct got_object_id **theirs, int ntheirs,
     struct got_object_id **ours, int nours, struct got_repository *repo,
-    int loose_obj_only, got_cancel_cb cancel_cb, void *cancel_arg)
+    int loose_obj_only, got_pack_progress_cb progress_cb, void *progress_arg,
+    struct got_ratelimit *rl, got_cancel_cb cancel_cb, void *cancel_arg)
 {
 	const struct got_error *err = NULL;
 	struct got_object_id **ids = NULL;
 	int i, nobj = 0, obj_type;
 
-	err = findtwixt(&ids, &nobj, ours, nours, theirs, ntheirs, repo,
-	    cancel_cb, cancel_arg);
+	*ncolored = 0;
+	*nfound = 0;
+	*ntrees = 0;
+
+	err = findtwixt(&ids, &nobj, ncolored, ours, nours, theirs, ntheirs,
+	    repo, progress_cb, progress_arg, rl, cancel_cb, cancel_arg);
 	if (err || nobj == 0)
 		goto done;
 
@@ -1350,8 +1415,9 @@ load_object_ids(struct got_object_idset *idset,
 			return err;
 		if (obj_type != GOT_OBJ_TYPE_COMMIT)
 			continue;
-		err = load_commit(0, idset, id, repo,
-		    loose_obj_only, cancel_cb, cancel_arg);
+		err = load_commit(0, idset, id, repo, loose_obj_only,
+		    ncolored, nfound, ntrees, progress_cb, progress_arg, rl,
+		    cancel_cb, cancel_arg);
 		if (err)
 			goto done;
 	}
@@ -1370,15 +1436,17 @@ load_object_ids(struct got_object_idset *idset,
 			obj_type = m->obj_type;
 		if (obj_type != GOT_OBJ_TYPE_TAG)
 			continue;
-		err = load_tag(0, idset, id, repo,
-		    loose_obj_only, cancel_cb, cancel_arg);
+		err = load_tag(0, idset, id, repo, loose_obj_only,
+		    ncolored, nfound, ntrees, progress_cb, progress_arg, rl,
+		    cancel_cb, cancel_arg);
 		if (err)
 			goto done;
 	}
 
 	for (i = 0; i < nobj; i++) {
-		err = load_commit(1, idset, ids[i], repo,
-		    loose_obj_only, cancel_cb, cancel_arg);
+		err = load_commit(1, idset, ids[i], repo, loose_obj_only,
+		    ncolored, nfound, ntrees, progress_cb, progress_arg, rl,
+		    cancel_cb, cancel_arg);
 		if (err)
 			goto done;
 	}
@@ -1397,8 +1465,9 @@ load_object_ids(struct got_object_idset *idset,
 			obj_type = m->obj_type;
 		if (obj_type != GOT_OBJ_TYPE_TAG)
 			continue;
-		err = load_tag(1, idset, id, repo,
-		    loose_obj_only, cancel_cb, cancel_arg);
+		err = load_tag(1, idset, id, repo, loose_obj_only,
+		    ncolored, nfound, ntrees, progress_cb, progress_arg, rl,
+		    cancel_cb, cancel_arg);
 		if (err)
 			goto done;
 	}
@@ -1625,7 +1694,8 @@ static const struct got_error *
 genpack(uint8_t *pack_sha1, FILE *packfile, FILE *delta_cache,
     struct got_pack_meta **deltify, int ndeltify,
     struct got_pack_meta **reuse, int nreuse,
-    int nours, struct got_repository *repo,
+    int ncolored, int nfound, int ntrees, int nours,
+    struct got_repository *repo,
     got_pack_progress_cb progress_cb, void *progress_arg,
     struct got_ratelimit *rl,
     got_cancel_cb cancel_cb, void *cancel_arg)
@@ -1657,8 +1727,8 @@ genpack(uint8_t *pack_sha1, FILE *packfile, FILE *delt
 	    write_order_cmp);
 	for (i = 0; i < ndeltify; i++) {
 		err = report_progress(progress_cb, progress_arg, rl,
-		    packfile_size, nours, ndeltify + nreuse,
-		    ndeltify + nreuse, i);
+		    ncolored, nfound, ntrees, packfile_size, nours,
+		    ndeltify + nreuse, ndeltify + nreuse, i);
 		if (err)
 			goto done;
 		m = deltify[i];
@@ -1672,8 +1742,8 @@ genpack(uint8_t *pack_sha1, FILE *packfile, FILE *delt
 	    reuse_write_order_cmp);
 	for (i = 0; i < nreuse; i++) {
 		err = report_progress(progress_cb, progress_arg, rl,
-		    packfile_size, nours, ndeltify + nreuse,
-		    ndeltify + nreuse, ndeltify + i);
+		    ncolored, nfound, ntrees, packfile_size, nours,
+		    ndeltify + nreuse, ndeltify + nreuse, ndeltify + i);
 		if (err)
 			goto done;
 		m = reuse[i];
@@ -1690,9 +1760,9 @@ genpack(uint8_t *pack_sha1, FILE *packfile, FILE *delt
 	packfile_size += SHA1_DIGEST_LENGTH;
 	packfile_size += sizeof(struct got_packfile_hdr);
 	if (progress_cb) {
-		err = progress_cb(progress_arg, packfile_size, nours,
-		    ndeltify + nreuse, ndeltify + nreuse,
-		    ndeltify + nreuse);
+		err = progress_cb(progress_arg, ncolored, nfound, ntrees,
+		    packfile_size, nours, ndeltify + nreuse,
+		    ndeltify + nreuse, ndeltify + nreuse);
 		if (err)
 			goto done;
 	}
@@ -1749,6 +1819,7 @@ got_pack_create(uint8_t *packsha1, FILE *packfile,
 	struct got_object_idset *idset;
 	struct got_ratelimit rl;
 	struct got_pack_metavec deltify, reuse;
+	int ncolored = 0, nfound = 0, ntrees = 0;
 
 	memset(&deltify, 0, sizeof(deltify));
 	memset(&reuse, 0, sizeof(reuse));
@@ -1759,8 +1830,9 @@ got_pack_create(uint8_t *packsha1, FILE *packfile,
 	if (idset == NULL)
 		return got_error_from_errno("got_object_idset_alloc");
 
-	err = load_object_ids(idset, theirs, ntheirs, ours, nours,
-	    repo, loose_obj_only, cancel_cb, cancel_arg);
+	err = load_object_ids(&ncolored, &nfound, &ntrees, idset, theirs,
+	    ntheirs, ours, nours, repo, loose_obj_only,
+	    progress_cb, progress_arg, &rl, cancel_cb, cancel_arg);
 	if (err)
 		return err;
 
@@ -1770,8 +1842,8 @@ got_pack_create(uint8_t *packsha1, FILE *packfile,
 		goto done;
 
 	if (progress_cb) {
-		err = progress_cb(progress_arg, 0L, nours,
-		    got_object_idset_num_elements(idset), 0, 0);
+		err = progress_cb(progress_arg, ncolored, nfound, ntrees,
+		    0L, nours, got_object_idset_num_elements(idset), 0, 0);
 		if (err)
 			goto done;
 	}
@@ -1795,8 +1867,9 @@ got_pack_create(uint8_t *packsha1, FILE *packfile,
 		goto done;
 	}
 
-	err = search_deltas(&reuse, idset, delta_cache_fd, nours, repo,
-	    progress_cb, progress_arg, &rl, cancel_cb, cancel_arg);
+	err = search_deltas(&reuse, idset, delta_cache_fd, ncolored, nfound,
+	    ntrees, nours, repo, progress_cb, progress_arg, &rl,
+	    cancel_cb, cancel_arg);
 	if (err)
 		goto done;
 	if (reuse.nmeta > 0) {
@@ -1830,8 +1903,8 @@ got_pack_create(uint8_t *packsha1, FILE *packfile,
 	if (err)
 		goto done;
 	if (deltify.nmeta > 0) {
-		err = pick_deltas(deltify.meta, deltify.nmeta, nours,
-		    reuse.nmeta, delta_cache, repo,
+		err = pick_deltas(deltify.meta, deltify.nmeta, ncolored,
+		    nfound, ntrees, nours, reuse.nmeta, delta_cache, repo,
 		    progress_cb, progress_arg, &rl, cancel_cb, cancel_arg);
 		if (err)
 			goto done;
@@ -1842,8 +1915,9 @@ got_pack_create(uint8_t *packsha1, FILE *packfile,
 	}
 
 	err = genpack(packsha1, packfile, delta_cache, deltify.meta,
-	    deltify.nmeta, reuse.meta, reuse.nmeta, nours, repo,
-	    progress_cb, progress_arg, &rl, cancel_cb, cancel_arg);
+	    deltify.nmeta, reuse.meta, reuse.nmeta, ncolored, nfound, ntrees,
+	    nours, repo, progress_cb, progress_arg, &rl,
+	    cancel_cb, cancel_arg);
 	if (err)
 		goto done;
 done:
blob - 0576ad42d0f1ba289507bd309c4b24c1bb0f2dbb
blob + b8290d0d6137059bea61a547bbbf82d00672571d
--- lib/send.c
+++ lib/send.c
@@ -105,6 +105,9 @@ struct pack_progress_arg {
     got_send_progress_cb progress_cb;
     void *progress_arg;
 
+    int ncolored;
+    int nfound;
+    int ntrees;
     off_t packfile_size;
     int ncommits;
     int nobj_total;
@@ -113,17 +116,22 @@ struct pack_progress_arg {
 };
 
 static const struct got_error *
-pack_progress(void *arg, off_t packfile_size, int ncommits,
-    int nobj_total, int nobj_deltify, int nobj_written)
+pack_progress(void *arg, int ncolored, int nfound, int ntrees,
+    off_t packfile_size, int ncommits, int nobj_total, int nobj_deltify,
+    int nobj_written)
 {
 	const struct got_error *err;
 	struct pack_progress_arg *a = arg;
 
-	err = a->progress_cb(a->progress_arg, packfile_size, ncommits,
-	    nobj_total, nobj_deltify, nobj_written, 0, NULL, 0);
+	err = a->progress_cb(a->progress_arg, ncolored, nfound, ntrees,
+	    packfile_size, ncommits, nobj_total, nobj_deltify,
+	    nobj_written, 0, NULL, 0);
 	if (err)
 		return err;
 
+	a->ncolored= ncolored;
+	a->nfound = nfound;
+	a->ntrees = ntrees;
 	a->packfile_size = packfile_size;
 	a->ncommits = ncommits;
 	a->nobj_total = nobj_total;
@@ -684,7 +692,8 @@ got_send_pack(const char *remote_name, struct got_path
 		}
 		if (refname != NULL ||
 		    bytes_sent_cur != bytes_sent) {
-			err = progress_cb(progress_arg, ppa.packfile_size,
+			err = progress_cb(progress_arg, ppa.ncolored,
+			    ppa.nfound, ppa.ntrees, ppa.packfile_size,
 			    ppa.ncommits, ppa.nobj_total, ppa.nobj_deltify,
 			    ppa.nobj_written, bytes_sent,
 			    refname, success);
blob - 597e601e0fefb3fbe64e77e4c05e3ae7103dd8b3
blob + 2ac3207e191fd1b940a418ffd18b2c0b82a89dff
--- regress/cmdline/pack.sh
+++ regress/cmdline/pack.sh
@@ -304,7 +304,7 @@ test_pack_ambiguous_arg() {
 	local commit1=`git_show_branch_head $testroot/repo mybranch`
 
 	gotadmin pack -r $testroot/repo -x master master \
-		> $testroot/stdout 2> $testroot/stderr
+		> /dev/null 2> $testroot/stderr
 	ret="$?"
 	if [ "$ret" = "0" ]; then
 		echo "gotadmin pack succeeded unexpectedly" >&2
@@ -312,15 +312,6 @@ test_pack_ambiguous_arg() {
 		return 1
 	fi
 
-	printf "\rpacking 1 reference\n" > $testroot/stdout.expected
-	cmp -s $testroot/stdout.expected $testroot/stdout
-	ret="$?"
-	if [ "$ret" != "0" ]; then
-		diff -u $testroot/stdout.expected $testroot/stdout
-		test_done "$testroot" "$ret"
-		return 1
-	fi
-
 	echo "gotadmin: not enough objects to pack" > $testroot/stderr.expected
 	cmp -s $testroot/stderr.expected $testroot/stderr
 	ret="$?"