@matheusbsbs / matheus-bagliano / commits / 6d21bf96b5
Fork 0

Refactor "tracking statistics" code used by "git checkout"

People seem to like "Your branch is ahead by N commit" report made by "git checkout", but the interface into the statistics function was a bit clunky. This splits the function into three parts: * The core "commit counting" function that takes "struct branch" and returns number of commits to show if we are ahead, behind or forked; * Convenience "stat formating" function that takes "struct branch" and formats the report into a given strbuf, using the above function; * "checkout" specific function that takes "branch_info" (type that is internal to checkout implementation), calls the above function and print the formatted result. in the hope that the former two can be more easily reusable. Signed-off-by: Junio C Hamano <gitster@pobox.com>

Junio C Hamano committed Jul 2, 2008 at 00:51 UTC 6d21bf96b59cbcc818fdc83b654d7fc83dd2c9cd
3 files changed +123 -88
builtin-checkout.c
+6 -88
@@ -305,97 +305,15 @@ static int merge_working_tree(struct checkout_opts *opts,
305 return 0;
306 }
307
308 -static void report_tracking(struct branch_info *new, struct checkout_opts *opts)
308 +static void report_tracking(struct branch_info *new)
309 {
310 - /*
311 - * We have switched to a new branch; is it building on
312 - * top of another branch, and if so does that other branch
313 - * have changes we do not have yet?
314 - */
315 - char *base;
316 - unsigned char sha1[20];
317 - struct commit *ours, *theirs;
318 - char symmetric[84];
319 - struct rev_info revs;
320 - const char *rev_argv[10];
321 - int rev_argc;
322 - int num_ours, num_theirs;
323 - const char *remote_msg;
310 + struct strbuf sb = STRBUF_INIT;
311 struct branch *branch = branch_get(new->name);
312
326 - /*
327 - * Nothing to report unless we are marked to build on top of
328 - * somebody else.
329 - */
330 - if (!branch || !branch->merge || !branch->merge[0] || !branch->merge[0]->dst)
331 - return;
332 -
333 - /*
334 - * If what we used to build on no longer exists, there is
335 - * nothing to report.
336 - */
337 - base = branch->merge[0]->dst;
338 - if (!resolve_ref(base, sha1, 1, NULL))
313 + if (!format_tracking_info(branch, &sb))
314 return;
340 -
341 - theirs = lookup_commit(sha1);
342 - ours = new->commit;
343 - if (!hashcmp(sha1, ours->object.sha1))
344 - return; /* we are the same */
345 -
346 - /* Run "rev-list --left-right ours...theirs" internally... */
347 - rev_argc = 0;
348 - rev_argv[rev_argc++] = NULL;
349 - rev_argv[rev_argc++] = "--left-right";
350 - rev_argv[rev_argc++] = symmetric;
351 - rev_argv[rev_argc++] = "--";
352 - rev_argv[rev_argc] = NULL;
353 -
354 - strcpy(symmetric, sha1_to_hex(ours->object.sha1));
355 - strcpy(symmetric + 40, "...");
356 - strcpy(symmetric + 43, sha1_to_hex(theirs->object.sha1));
357 -
358 - init_revisions(&revs, NULL);
359 - setup_revisions(rev_argc, rev_argv, &revs, NULL);
360 - prepare_revision_walk(&revs);
361 -
362 - /* ... and count the commits on each side. */
363 - num_ours = 0;
364 - num_theirs = 0;
365 - while (1) {
366 - struct commit *c = get_revision(&revs);
367 - if (!c)
368 - break;
369 - if (c->object.flags & SYMMETRIC_LEFT)
370 - num_ours++;
371 - else
372 - num_theirs++;
373 - }
374 -
375 - if (!prefixcmp(base, "refs/remotes/")) {
376 - remote_msg = " remote";
377 - base += strlen("refs/remotes/");
378 - } else {
379 - remote_msg = "";
380 - }
381 -
382 - if (!num_theirs)
383 - printf("Your branch is ahead of the tracked%s branch '%s' "
384 - "by %d commit%s.\n",
385 - remote_msg, base,
386 - num_ours, (num_ours == 1) ? "" : "s");
387 - else if (!num_ours)
388 - printf("Your branch is behind the tracked%s branch '%s' "
389 - "by %d commit%s,\n"
390 - "and can be fast-forwarded.\n",
391 - remote_msg, base,
392 - num_theirs, (num_theirs == 1) ? "" : "s");
393 - else
394 - printf("Your branch and the tracked%s branch '%s' "
395 - "have diverged,\nand respectively "
396 - "have %d and %d different commit(s) each.\n",
397 - remote_msg, base,
398 - num_ours, num_theirs);
315 + fputs(sb.buf, stdout);
316 + strbuf_release(&sb);
317 }
318
319 static void update_refs_for_switch(struct checkout_opts *opts,
@@ -441,7 +359,7 @@ static void update_refs_for_switch(struct checkout_opts *opts,
359 remove_branch_state();
360 strbuf_release(&msg);
361 if (!opts->quiet && (new->path || !strcmp(new->name, "HEAD")))
444 - report_tracking(new, opts);
362 + report_tracking(new);
363 }
364
365 static int switch_branches(struct checkout_opts *opts, struct branch_info *new)
remote.c
+113
@@ -1,6 +1,9 @@
1 #include "cache.h"
2 #include "remote.h"
3 #include "refs.h"
4 +#include "commit.h"
5 +#include "diff.h"
6 +#include "revision.h"
7
8 static struct refspec s_tag_refspec = {
9 0,
@@ -1222,3 +1225,113 @@ int resolve_remote_symref(struct ref *ref, struct ref *list)
1225 }
1226 return 1;
1227 }
1228 +
1229 +/*
1230 + * Return true if there is anything to report, otherwise false.
1231 + */
1232 +int stat_tracking_info(struct branch *branch, int *num_ours, int *num_theirs)
1233 +{
1234 + unsigned char sha1[20];
1235 + struct commit *ours, *theirs;
1236 + char symmetric[84];
1237 + struct rev_info revs;
1238 + const char *rev_argv[10], *base;
1239 + int rev_argc;
1240 +
1241 + /*
1242 + * Nothing to report unless we are marked to build on top of
1243 + * somebody else.
1244 + */
1245 + if (!branch ||
1246 + !branch->merge || !branch->merge[0] || !branch->merge[0]->dst)
1247 + return 0;
1248 +
1249 + /*
1250 + * If what we used to build on no longer exists, there is
1251 + * nothing to report.
1252 + */
1253 + base = branch->merge[0]->dst;
1254 + if (!resolve_ref(base, sha1, 1, NULL))
1255 + return 0;
1256 + theirs = lookup_commit(sha1);
1257 + if (!theirs)
1258 + return 0;
1259 +
1260 + if (!resolve_ref(branch->refname, sha1, 1, NULL))
1261 + return 0;
1262 + ours = lookup_commit(sha1);
1263 + if (!ours)
1264 + return 0;
1265 +
1266 + /* are we the same? */
1267 + if (theirs == ours)
1268 + return 0;
1269 +
1270 + /* Run "rev-list --left-right ours...theirs" internally... */
1271 + rev_argc = 0;
1272 + rev_argv[rev_argc++] = NULL;
1273 + rev_argv[rev_argc++] = "--left-right";
1274 + rev_argv[rev_argc++] = symmetric;
1275 + rev_argv[rev_argc++] = "--";
1276 + rev_argv[rev_argc] = NULL;
1277 +
1278 + strcpy(symmetric, sha1_to_hex(ours->object.sha1));
1279 + strcpy(symmetric + 40, "...");
1280 + strcpy(symmetric + 43, sha1_to_hex(theirs->object.sha1));
1281 +
1282 + init_revisions(&revs, NULL);
1283 + setup_revisions(rev_argc, rev_argv, &revs, NULL);
1284 + prepare_revision_walk(&revs);
1285 +
1286 + /* ... and count the commits on each side. */
1287 + *num_ours = 0;
1288 + *num_theirs = 0;
1289 + while (1) {
1290 + struct commit *c = get_revision(&revs);
1291 + if (!c)
1292 + break;
1293 + if (c->object.flags & SYMMETRIC_LEFT)
1294 + (*num_ours)++;
1295 + else
1296 + (*num_theirs)++;
1297 + }
1298 + return 1;
1299 +}
1300 +
1301 +/*
1302 + * Return true when there is anything to report, otherwise false.
1303 + */
1304 +int format_tracking_info(struct branch *branch, struct strbuf *sb)
1305 +{
1306 + int num_ours, num_theirs;
1307 + const char *base, *remote_msg;
1308 +
1309 + if (!stat_tracking_info(branch, &num_ours, &num_theirs))
1310 + return 0;
1311 +
1312 + base = branch->merge[0]->dst;
1313 + if (!prefixcmp(base, "refs/remotes/")) {
1314 + remote_msg = " remote";
1315 + base += strlen("refs/remotes/");
1316 + } else {
1317 + remote_msg = "";
1318 + }
1319 + if (!num_theirs)
1320 + strbuf_addf(sb, "Your branch is ahead of the tracked%s branch '%s' "
1321 + "by %d commit%s.\n",
1322 + remote_msg, base,
1323 + num_ours, (num_ours == 1) ? "" : "s");
1324 + else if (!num_ours)
1325 + strbuf_addf(sb, "Your branch is behind the tracked%s branch '%s' "
1326 + "by %d commit%s,\n"
1327 + "and can be fast-forwarded.\n",
1328 + remote_msg, base,
1329 + num_theirs, (num_theirs == 1) ? "" : "s");
1330 + else
1331 + strbuf_addf(sb, "Your branch and the tracked%s branch '%s' "
1332 + "have diverged,\nand respectively "
1333 + "have %d and %d different commit(s) each.\n",
1334 + remote_msg, base,
1335 + num_ours, num_theirs);
1336 + return 1;
1337 +}
remote.h
+4
@@ -129,4 +129,8 @@ enum match_refs_flags {
129 MATCH_REFS_MIRROR = (1 << 1),
130 };
131
132 +/* Reporting of tracking info */
133 +int stat_tracking_info(struct branch *branch, int *num_ours, int *num_theirs);
134 +int format_tracking_info(struct branch *branch, struct strbuf *sb);
135 +
136 #endif