static void gc_config(void) { const char *value; if (!git_config_get_value("gc.packrefs", &value)) { if (value && !strcmp(value, "notbare")) pack_refs = -1; else pack_refs = git_config_bool("gc.packrefs", value); } git_config_get_int("gc.aggressivewindow", &aggressive_window); git_config_get_int("gc.aggressivedepth", &aggressive_depth); git_config_get_int("gc.auto", &gc_auto_threshold); git_config_get_int("gc.autopacklimit", &gc_auto_pack_limit); git_config_get_bool("gc.autodetach", &detach_auto); if (!git_config_get_string_const("gc.pruneexpire", &prune_expire)) { if (strcmp(prune_expire, "now")) { unsigned long now = approxidate("now"); if (approxidate(prune_expire) >= now) { git_die_config("gc.pruneexpire", _("Invalid gc.pruneexpire: '%s'"), prune_expire); } } } git_config(git_default_config, NULL); }
static int gc_config(const char *var, const char *value, void *cb) { if (!strcmp(var, "gc.packrefs")) { if (value && !strcmp(value, "notbare")) pack_refs = -1; else pack_refs = git_config_bool(var, value); return 0; } if (!strcmp(var, "gc.aggressivewindow")) { aggressive_window = git_config_int(var, value); return 0; } if (!strcmp(var, "gc.auto")) { gc_auto_threshold = git_config_int(var, value); return 0; } if (!strcmp(var, "gc.autopacklimit")) { gc_auto_pack_limit = git_config_int(var, value); return 0; } if (!strcmp(var, "gc.pruneexpire")) { if (!value) return config_error_nonbool(var); if (strcmp(value, "now")) { unsigned long now = approxidate("now"); if (approxidate(value) >= now) return error("Invalid %s: '%s'", var, value); } prune_expire = xstrdup(value); return 0; } return git_default_config(var, value, cb); }
static void git_config_date_string(const char *key, const char **output) { if (git_config_get_string_const(key, output)) return; if (strcmp(*output, "now")) { unsigned long now = approxidate("now"); if (approxidate(*output) >= now) git_die_config(key, _("Invalid %s: '%s'"), key, *output); } }
int main() { long usec; struct timeval start, end; gettimeofday(&start, NULL); for (int i = 0; i < ROUNDS; i++) { struct timeval t; approxidate("10/Mar/2013:00:00:02.003 -0500", &t); } gettimeofday(&end, NULL); usec = end.tv_usec - start.tv_usec; double approxidate_time = usec/((double)(1000*1000)); approxidate_time += end.tv_sec - start.tv_sec; gettimeofday(&start, NULL); for (int i = 0; i < ROUNDS; i++) { struct tm m; strptime("10/Mar/2013:00:00:02", "%d/%b/%Y:%T", &m); } gettimeofday(&end, NULL); usec = end.tv_usec - start.tv_usec; double strptime_time = usec/((double)(1000*1000)); strptime_time += end.tv_sec - start.tv_sec; printf("approxidate time: %lf\n", approxidate_time); printf("strptime time: %lf\n", strptime_time); return 0; }
static int gc_config(const char *var, const char *value, void *cb) { if (!strcmp(var, "gc.packrefs")) { if (value && !strcmp(value, "notbare")) pack_refs = -1; else pack_refs = git_config_bool(var, value); return 0; } if (!strcmp(var, "gc.aggressivewindow")) { aggressive_window = git_config_int(var, value); return 0; } if (!strcmp(var, "gc.aggressivedepth")) { aggressive_depth = git_config_int(var, value); return 0; } if (!strcmp(var, "gc.auto")) { gc_auto_threshold = git_config_int(var, value); return 0; } if (!strcmp(var, "gc.autopacklimit")) { gc_auto_pack_limit = git_config_int(var, value); return 0; } if (!strcmp(var, "gc.autodetach")) { detach_auto = git_config_bool(var, value); return 0; } if (!strcmp(var, "gc.pruneexpire")) { if (value && strcmp(value, "now")) { unsigned long now = approxidate("now"); if (approxidate(value) >= now) return error(_("Invalid %s: '%s'"), var, value); } return git_config_string(&prune_expire, var, value); } if (!strcmp(var, "gc.prunereposexpire")) { if (value && strcmp(value, "now")) { unsigned long now = approxidate("now"); if (approxidate(value) >= now) return error(_("Invalid %s: '%s'"), var, value); } return git_config_string(&prune_repos_expire, var, value); } return git_default_config(var, value, cb); }
static void show_datestring(const char *flag, const char *datestr) { static char buffer[100]; /* date handling requires both flags and revs */ if ((filter & (DO_FLAGS | DO_REVS)) != (DO_FLAGS | DO_REVS)) return; snprintf(buffer, sizeof(buffer), "%s%lu", flag, approxidate(datestr)); show(buffer); }
static void parse_approxidate(char **argv) { char buff[100]; for (; *argv; argv++) { time_t t; t = approxidate(*argv); strftime(buff, 100, "%d/%m/%Y %H:%M:%S", localtime(&t)); printf("%s -> %s\n", *argv, buff); } }
static void show_datestring(const char *flag, const char *datestr) { char *buffer; /* date handling requires both flags and revs */ if ((filter & (DO_FLAGS | DO_REVS)) != (DO_FLAGS | DO_REVS)) return; buffer = xstrfmt("%s%"PRItime, flag, approxidate(datestr)); show(buffer); free(buffer); }
static int l_tm_approxidate_milli (lua_State *L) { char* date_string = (char*)colony_toutf8(L, 1); struct timeval tv; approxidate(date_string, &tv); double sec = (double)tv.tv_sec; double usec = (double)tv.tv_usec; double millisec = sec * 1000; double micro_milli = floor(usec/1000); double since_epoch = millisec+micro_milli; lua_pushnumber(L, since_epoch); return 1; }
static void add_shallow_requests(struct strbuf *req_buf, const struct fetch_pack_args *args) { if (is_repository_shallow(the_repository)) write_shallow_commits(req_buf, 1, NULL); if (args->depth > 0) packet_buf_write(req_buf, "deepen %d", args->depth); if (args->deepen_since) { timestamp_t max_age = approxidate(args->deepen_since); packet_buf_write(req_buf, "deepen-since %"PRItime, max_age); } if (args->deepen_not) { int i; for (i = 0; i < args->deepen_not->nr; i++) { struct string_list_item *s = args->deepen_not->items + i; packet_buf_write(req_buf, "deepen-not %s", s->string); } } }
int parse_opt_approxidate_cb(const struct option *opt, const char *arg, int unset) { *(unsigned long *)(opt->value) = approxidate(arg); return 0; }
int add_reflog_for_walk(struct reflog_walk_info *info, struct commit *commit, const char *name) { timestamp_t timestamp = 0; int recno = -1; struct string_list_item *item; struct complete_reflogs *reflogs; char *branch, *at = strchr(name, '@'); struct commit_reflog *commit_reflog; enum selector_type selector = SELECTOR_NONE; if (commit->object.flags & UNINTERESTING) die ("Cannot walk reflogs for %s", name); branch = xstrdup(name); if (at && at[1] == '{') { char *ep; branch[at - name] = '\0'; recno = strtoul(at + 2, &ep, 10); if (*ep != '}') { recno = -1; timestamp = approxidate(at + 2); selector = SELECTOR_DATE; } else selector = SELECTOR_INDEX; } else recno = 0; item = string_list_lookup(&info->complete_reflogs, branch); if (item) reflogs = item->util; else { if (*branch == '\0') { struct object_id oid; free(branch); branch = resolve_refdup("HEAD", 0, oid.hash, NULL); if (!branch) die ("No current branch"); } reflogs = read_complete_reflog(branch); if (!reflogs || reflogs->nr == 0) { struct object_id oid; char *b; int ret = dwim_log(branch, strlen(branch), oid.hash, &b); if (ret > 1) free(b); else if (ret == 1) { if (reflogs) { free(reflogs->ref); free(reflogs); } free(branch); branch = b; reflogs = read_complete_reflog(branch); } } if (!reflogs || reflogs->nr == 0) { if (reflogs) { free(reflogs->ref); free(reflogs); } free(branch); return -1; } string_list_insert(&info->complete_reflogs, branch)->util = reflogs; } free(branch); commit_reflog = xcalloc(1, sizeof(struct commit_reflog)); if (recno < 0) { commit_reflog->recno = get_reflog_recno_by_time(reflogs, timestamp); if (commit_reflog->recno < 0) { if (reflogs) { free(reflogs->ref); free(reflogs); } free(commit_reflog); return -1; } } else commit_reflog->recno = reflogs->nr - recno - 1; commit_reflog->selector = selector; commit_reflog->reflogs = reflogs; add_commit_info(commit, commit_reflog, &info->reflogs); return 0; }
static int cmd_reflog_delete(int argc, const char **argv, const char *prefix) { struct expire_reflog_policy_cb cb; int i, status = 0; unsigned int flags = 0; memset(&cb, 0, sizeof(cb)); for (i = 1; i < argc; i++) { const char *arg = argv[i]; if (!strcmp(arg, "--dry-run") || !strcmp(arg, "-n")) flags |= EXPIRE_REFLOGS_DRY_RUN; else if (!strcmp(arg, "--rewrite")) flags |= EXPIRE_REFLOGS_REWRITE; else if (!strcmp(arg, "--updateref")) flags |= EXPIRE_REFLOGS_UPDATE_REF; else if (!strcmp(arg, "--verbose")) flags |= EXPIRE_REFLOGS_VERBOSE; else if (!strcmp(arg, "--")) { i++; break; } else if (arg[0] == '-') usage(_(reflog_delete_usage)); else break; } if (argc - i < 1) return error(_("no reflog specified to delete")); for ( ; i < argc; i++) { const char *spec = strstr(argv[i], "@{"); struct object_id oid; char *ep, *ref; int recno; if (!spec) { status |= error(_("not a reflog: %s"), argv[i]); continue; } if (!dwim_log(argv[i], spec - argv[i], &oid, &ref)) { status |= error(_("no reflog for '%s'"), argv[i]); continue; } recno = strtoul(spec + 2, &ep, 10); if (*ep == '}') { cb.cmd.recno = -recno; for_each_reflog_ent(ref, count_reflog_ent, &cb); } else { cb.cmd.expire_total = approxidate(spec + 2); for_each_reflog_ent(ref, count_reflog_ent, &cb); cb.cmd.expire_total = 0; } status |= reflog_expire(ref, &oid, flags, reflog_expiry_prepare, should_expire_reflog_ent, reflog_expiry_cleanup, &cb); free(ref); } return status; }
static int handle_revision_opt(struct rev_info *revs, int argc, const char **argv, int *unkc, const char **unkv) { const char *arg = argv[0]; /* pseudo revision arguments */ if (!strcmp(arg, "--all") || !strcmp(arg, "--branches") || !strcmp(arg, "--tags") || !strcmp(arg, "--remotes") || !strcmp(arg, "--reflog") || !strcmp(arg, "--not") || !strcmp(arg, "--no-walk") || !strcmp(arg, "--do-walk")) { unkv[(*unkc)++] = arg; return 1; } if (!prefixcmp(arg, "--max-count=")) { revs->max_count = atoi(arg + 12); } else if (!prefixcmp(arg, "--skip=")) { revs->skip_count = atoi(arg + 7); } else if ((*arg == '-') && isdigit(arg[1])) { /* accept -<digit>, like traditional "head" */ revs->max_count = atoi(arg + 1); } else if (!strcmp(arg, "-n")) { if (argc <= 1) return error("-n requires an argument"); revs->max_count = atoi(argv[1]); return 2; } else if (!prefixcmp(arg, "-n")) { revs->max_count = atoi(arg + 2); } else if (!prefixcmp(arg, "--max-age=")) { revs->max_age = atoi(arg + 10); } else if (!prefixcmp(arg, "--since=")) { revs->max_age = approxidate(arg + 8); } else if (!prefixcmp(arg, "--after=")) { revs->max_age = approxidate(arg + 8); } else if (!prefixcmp(arg, "--min-age=")) { revs->min_age = atoi(arg + 10); } else if (!prefixcmp(arg, "--before=")) { revs->min_age = approxidate(arg + 9); } else if (!prefixcmp(arg, "--until=")) { revs->min_age = approxidate(arg + 8); } else if (!strcmp(arg, "--first-parent")) { revs->first_parent_only = 1; } else if (!strcmp(arg, "-g") || !strcmp(arg, "--walk-reflogs")) { init_reflog_walk(&revs->reflog_info); } else if (!strcmp(arg, "--default")) { if (argc <= 1) return error("bad --default argument"); revs->def = argv[1]; return 2; } else if (!strcmp(arg, "--merge")) { revs->show_merge = 1; } else if (!strcmp(arg, "--topo-order")) { revs->lifo = 1; revs->topo_order = 1; } else if (!strcmp(arg, "--simplify-merges")) { revs->simplify_merges = 1; revs->rewrite_parents = 1; revs->simplify_history = 0; revs->limited = 1; } else if (!strcmp(arg, "--date-order")) { revs->lifo = 0; revs->topo_order = 1; } else if (!prefixcmp(arg, "--early-output")) { int count = 100; switch (arg[14]) { case '=': count = atoi(arg+15); /* Fallthrough */ case 0: revs->topo_order = 1; revs->early_output = count; } } else if (!strcmp(arg, "--parents")) { revs->rewrite_parents = 1; revs->print_parents = 1; } else if (!strcmp(arg, "--dense")) { revs->dense = 1; } else if (!strcmp(arg, "--sparse")) { revs->dense = 0; } else if (!strcmp(arg, "--show-all")) { revs->show_all = 1; } else if (!strcmp(arg, "--remove-empty")) { revs->remove_empty_trees = 1; } else if (!strcmp(arg, "--no-merges")) { revs->no_merges = 1; } else if (!strcmp(arg, "--boundary")) { revs->boundary = 1; } else if (!strcmp(arg, "--left-right")) { revs->left_right = 1; } else if (!strcmp(arg, "--cherry-pick")) { revs->cherry_pick = 1; revs->limited = 1; } else if (!strcmp(arg, "--objects")) { revs->tag_objects = 1; revs->tree_objects = 1; revs->blob_objects = 1; } else if (!strcmp(arg, "--objects-edge")) { revs->tag_objects = 1; revs->tree_objects = 1; revs->blob_objects = 1; revs->edge_hint = 1; } else if (!strcmp(arg, "--unpacked")) { revs->unpacked = 1; free(revs->ignore_packed); revs->ignore_packed = NULL; revs->num_ignore_packed = 0; } else if (!prefixcmp(arg, "--unpacked=")) { revs->unpacked = 1; add_ignore_packed(revs, arg+11); } else if (!strcmp(arg, "-r")) { revs->diff = 1; DIFF_OPT_SET(&revs->diffopt, RECURSIVE); } else if (!strcmp(arg, "-t")) { revs->diff = 1; DIFF_OPT_SET(&revs->diffopt, RECURSIVE); DIFF_OPT_SET(&revs->diffopt, TREE_IN_RECURSIVE); } else if (!strcmp(arg, "-m")) { revs->ignore_merges = 0; } else if (!strcmp(arg, "-c")) { revs->diff = 1; revs->dense_combined_merges = 0; revs->combine_merges = 1; } else if (!strcmp(arg, "--cc")) { revs->diff = 1; revs->dense_combined_merges = 1; revs->combine_merges = 1; } else if (!strcmp(arg, "-v")) { revs->verbose_header = 1; } else if (!strcmp(arg, "--pretty")) { revs->verbose_header = 1; get_commit_format(arg+8, revs); } else if (!prefixcmp(arg, "--pretty=")) { revs->verbose_header = 1; get_commit_format(arg+9, revs); } else if (!strcmp(arg, "--graph")) { revs->topo_order = 1; revs->rewrite_parents = 1; revs->graph = graph_init(revs); } else if (!strcmp(arg, "--root")) { revs->show_root_diff = 1; } else if (!strcmp(arg, "--no-commit-id")) { revs->no_commit_id = 1; } else if (!strcmp(arg, "--always")) { revs->always_show_header = 1; } else if (!strcmp(arg, "--no-abbrev")) { revs->abbrev = 0; } else if (!strcmp(arg, "--abbrev")) { revs->abbrev = DEFAULT_ABBREV; } else if (!prefixcmp(arg, "--abbrev=")) { revs->abbrev = strtoul(arg + 9, NULL, 10); if (revs->abbrev < MINIMUM_ABBREV) revs->abbrev = MINIMUM_ABBREV; else if (revs->abbrev > 40) revs->abbrev = 40; } else if (!strcmp(arg, "--abbrev-commit")) { revs->abbrev_commit = 1; } else if (!strcmp(arg, "--full-diff")) { revs->diff = 1; revs->full_diff = 1; } else if (!strcmp(arg, "--full-history")) { revs->simplify_history = 0; } else if (!strcmp(arg, "--relative-date")) { revs->date_mode = DATE_RELATIVE; } else if (!strncmp(arg, "--date=", 7)) { revs->date_mode = parse_date_format(arg + 7); } else if (!strcmp(arg, "--log-size")) { revs->show_log_size = 1; } /* * Grepping the commit log */ else if (!prefixcmp(arg, "--author=")) { add_header_grep(revs, GREP_HEADER_AUTHOR, arg+9); } else if (!prefixcmp(arg, "--committer=")) { add_header_grep(revs, GREP_HEADER_COMMITTER, arg+12); } else if (!prefixcmp(arg, "--grep=")) { add_message_grep(revs, arg+7); } else if (!strcmp(arg, "--extended-regexp") || !strcmp(arg, "-E")) { revs->grep_filter.regflags |= REG_EXTENDED; } else if (!strcmp(arg, "--regexp-ignore-case") || !strcmp(arg, "-i")) { revs->grep_filter.regflags |= REG_ICASE; } else if (!strcmp(arg, "--fixed-strings") || !strcmp(arg, "-F")) { revs->grep_filter.fixed = 1; } else if (!strcmp(arg, "--all-match")) { revs->grep_filter.all_match = 1; } else if (!prefixcmp(arg, "--encoding=")) { arg += 11; if (strcmp(arg, "none")) git_log_output_encoding = xstrdup(arg); else git_log_output_encoding = ""; } else if (!strcmp(arg, "--reverse")) { revs->reverse ^= 1; } else if (!strcmp(arg, "--children")) { revs->children.name = "children"; revs->limited = 1; } else { int opts = diff_opt_parse(&revs->diffopt, argv, argc); if (!opts) unkv[(*unkc)++] = arg; return opts; } return 1; }
int cmd_show_branch(int ac, const char **av, const char *prefix) { struct commit *rev[MAX_REVS], *commit; char *reflog_msg[MAX_REVS]; struct commit_list *list = NULL, *seen = NULL; unsigned int rev_mask[MAX_REVS]; int num_rev, i, extra = 0; int all_heads = 0, all_remotes = 0; int all_mask, all_revs; int lifo = 1; char head[128]; const char *head_p; int head_len; unsigned char head_sha1[20]; int merge_base = 0; int independent = 0; int no_name = 0; int sha1_name = 0; int shown_merge_point = 0; int with_current_branch = 0; int head_at = -1; int topics = 0; int dense = 1; int reflog = 0; const char *reflog_base = NULL; git_config(git_show_branch_config); /* If nothing is specified, try the default first */ if (ac == 1 && default_num) { ac = default_num + 1; av = default_arg - 1; /* ick; we would not address av[0] */ } while (1 < ac && av[1][0] == '-') { const char *arg = av[1]; if (!strcmp(arg, "--")) { ac--; av++; break; } else if (!strcmp(arg, "--all") || !strcmp(arg, "-a")) all_heads = all_remotes = 1; else if (!strcmp(arg, "--remotes") || !strcmp(arg, "-r")) all_remotes = 1; else if (!strcmp(arg, "--more")) extra = 1; else if (!strcmp(arg, "--list")) extra = -1; else if (!strcmp(arg, "--no-name")) no_name = 1; else if (!strcmp(arg, "--current")) with_current_branch = 1; else if (!strcmp(arg, "--sha1-name")) sha1_name = 1; else if (!prefixcmp(arg, "--more=")) extra = atoi(arg + 7); else if (!strcmp(arg, "--merge-base")) merge_base = 1; else if (!strcmp(arg, "--independent")) independent = 1; else if (!strcmp(arg, "--topo-order")) lifo = 1; else if (!strcmp(arg, "--topics")) topics = 1; else if (!strcmp(arg, "--sparse")) dense = 0; else if (!strcmp(arg, "--date-order")) lifo = 0; else if (!strcmp(arg, "--reflog") || !strcmp(arg, "-g")) { reflog = DEFAULT_REFLOG; } else if (!prefixcmp(arg, "--reflog=")) parse_reflog_param(arg + 9, &reflog, &reflog_base); else if (!prefixcmp(arg, "-g=")) parse_reflog_param(arg + 3, &reflog, &reflog_base); else usage(show_branch_usage); ac--; av++; } ac--; av++; if (extra || reflog) { /* "listing" mode is incompatible with * independent nor merge-base modes. */ if (independent || merge_base) usage(show_branch_usage); if (reflog && ((0 < extra) || all_heads || all_remotes)) /* * Asking for --more in reflog mode does not * make sense. --list is Ok. * * Also --all and --remotes do not make sense either. */ usage(show_branch_usage_reflog); } /* If nothing is specified, show all branches by default */ if (ac + all_heads + all_remotes == 0) all_heads = 1; if (reflog) { unsigned char sha1[20]; char nth_desc[256]; char *ref; int base = 0; if (ac == 0) { static const char *fake_av[2]; const char *refname; refname = resolve_ref("HEAD", sha1, 1, NULL); fake_av[0] = xstrdup(refname); fake_av[1] = NULL; av = fake_av; ac = 1; } if (ac != 1) die("--reflog option needs one branch name"); if (MAX_REVS < reflog) die("Only %d entries can be shown at one time.", MAX_REVS); if (!dwim_ref(*av, strlen(*av), sha1, &ref)) die("No such ref %s", *av); /* Has the base been specified? */ if (reflog_base) { char *ep; base = strtoul(reflog_base, &ep, 10); if (*ep) { /* Ah, that is a date spec... */ unsigned long at; at = approxidate(reflog_base); read_ref_at(ref, at, -1, sha1, NULL, NULL, NULL, &base); } } for (i = 0; i < reflog; i++) { char *logmsg, *m; const char *msg; unsigned long timestamp; int tz; if (read_ref_at(ref, 0, base+i, sha1, &logmsg, ×tamp, &tz, NULL)) { reflog = i; break; } msg = strchr(logmsg, '\t'); if (!msg) msg = "(none)"; else msg++; m = xmalloc(strlen(msg) + 200); sprintf(m, "(%s) %s", show_date(timestamp, tz, 1), msg); reflog_msg[i] = m; free(logmsg); sprintf(nth_desc, "%s@{%d}", *av, base+i); append_ref(nth_desc, sha1, 1); } } else if (all_heads + all_remotes) snarf_refs(all_heads, all_remotes); else { while (0 < ac) { append_one_rev(*av); ac--; av++; } } head_p = resolve_ref("HEAD", head_sha1, 1, NULL); if (head_p) { head_len = strlen(head_p); memcpy(head, head_p, head_len + 1); } else { head_len = 0; head[0] = 0; } if (with_current_branch && head_p) { int has_head = 0; for (i = 0; !has_head && i < ref_name_cnt; i++) { /* We are only interested in adding the branch * HEAD points at. */ if (rev_is_head(head, head_len, ref_name[i], head_sha1, NULL)) has_head++; } if (!has_head) { int pfxlen = strlen("refs/heads/"); append_one_rev(head + pfxlen); } } if (!ref_name_cnt) { fprintf(stderr, "No revs to be shown.\n"); exit(0); } for (num_rev = 0; ref_name[num_rev]; num_rev++) { unsigned char revkey[20]; unsigned int flag = 1u << (num_rev + REV_SHIFT); if (MAX_REVS <= num_rev) die("cannot handle more than %d revs.", MAX_REVS); if (get_sha1(ref_name[num_rev], revkey)) die("'%s' is not a valid ref.", ref_name[num_rev]); commit = lookup_commit_reference(revkey); if (!commit) die("cannot find commit %s (%s)", ref_name[num_rev], revkey); parse_commit(commit); mark_seen(commit, &seen); /* rev#0 uses bit REV_SHIFT, rev#1 uses bit REV_SHIFT+1, * and so on. REV_SHIFT bits from bit 0 are used for * internal bookkeeping. */ commit->object.flags |= flag; if (commit->object.flags == flag) insert_by_date(commit, &list); rev[num_rev] = commit; } for (i = 0; i < num_rev; i++) rev_mask[i] = rev[i]->object.flags; if (0 <= extra) join_revs(&list, &seen, num_rev, extra); sort_by_date(&seen); if (merge_base) return show_merge_base(seen, num_rev); if (independent) return show_independent(rev, num_rev, ref_name, rev_mask); /* Show list; --more=-1 means list-only */ if (1 < num_rev || extra < 0) { for (i = 0; i < num_rev; i++) { int j; int is_head = rev_is_head(head, head_len, ref_name[i], head_sha1, rev[i]->object.sha1); if (extra < 0) printf("%c [%s] ", is_head ? '*' : ' ', ref_name[i]); else { for (j = 0; j < i; j++) putchar(' '); printf("%c [%s] ", is_head ? '*' : '!', ref_name[i]); } if (!reflog) { /* header lines never need name */ show_one_commit(rev[i], 1); } else puts(reflog_msg[i]); if (is_head) head_at = i; } if (0 <= extra) { for (i = 0; i < num_rev; i++) putchar('-'); putchar('\n'); } } if (extra < 0) exit(0); /* Sort topologically */ sort_in_topological_order(&seen, lifo); /* Give names to commits */ if (!sha1_name && !no_name) name_commits(seen, rev, ref_name, num_rev); all_mask = ((1u << (REV_SHIFT + num_rev)) - 1); all_revs = all_mask & ~((1u << REV_SHIFT) - 1); while (seen) { struct commit *commit = pop_one_commit(&seen); int this_flag = commit->object.flags; int is_merge_point = ((this_flag & all_revs) == all_revs); shown_merge_point |= is_merge_point; if (1 < num_rev) { int is_merge = !!(commit->parents && commit->parents->next); if (topics && !is_merge_point && (this_flag & (1u << REV_SHIFT))) continue; if (dense && is_merge && omit_in_dense(commit, rev, num_rev)) continue; for (i = 0; i < num_rev; i++) { int mark; if (!(this_flag & (1u << (i + REV_SHIFT)))) mark = ' '; else if (is_merge) mark = '-'; else if (i == head_at) mark = '*'; else mark = '+'; putchar(mark); } putchar(' '); } show_one_commit(commit, no_name); if (shown_merge_point && --extra < 0) break; } return 0; }
int parse_opt_approxidate_cb(const struct option *opt, const char *arg, int unset) { *(timestamp_t *)(opt->value) = approxidate(arg); return 0; }
int cmd_show_branch(int ac, const char **av, const char *prefix) { struct commit *rev[MAX_REVS], *commit; char *reflog_msg[MAX_REVS]; struct commit_list *list = NULL, *seen = NULL; unsigned int rev_mask[MAX_REVS]; int num_rev, i, extra = 0; int all_heads = 0, all_remotes = 0; int all_mask, all_revs; int lifo = 1; char head[128]; const char *head_p; int head_len; unsigned char head_sha1[20]; int merge_base = 0; int independent = 0; int no_name = 0; int sha1_name = 0; int shown_merge_point = 0; int with_current_branch = 0; int head_at = -1; int topics = 0; int dense = 1; const char *reflog_base = NULL; struct option builtin_show_branch_options[] = { OPT_BOOLEAN('a', "all", &all_heads, "show remote-tracking and local branches"), OPT_BOOLEAN('r', "remotes", &all_remotes, "show remote-tracking branches"), OPT__COLOR(&showbranch_use_color, "color '*!+-' corresponding to the branch"), { OPTION_INTEGER, 0, "more", &extra, "n", "show <n> more commits after the common ancestor", PARSE_OPT_OPTARG, NULL, (intptr_t)1 }, OPT_SET_INT(0, "list", &extra, "synonym to more=-1", -1), OPT_BOOLEAN(0, "no-name", &no_name, "suppress naming strings"), OPT_BOOLEAN(0, "current", &with_current_branch, "include the current branch"), OPT_BOOLEAN(0, "sha1-name", &sha1_name, "name commits with their object names"), OPT_BOOLEAN(0, "merge-base", &merge_base, "show possible merge bases"), OPT_BOOLEAN(0, "independent", &independent, "show refs unreachable from any other ref"), OPT_BOOLEAN(0, "topo-order", &lifo, "show commits in topological order"), OPT_BOOLEAN(0, "topics", &topics, "show only commits not on the first branch"), OPT_SET_INT(0, "sparse", &dense, "show merges reachable from only one tip", 0), OPT_SET_INT(0, "date-order", &lifo, "show commits where no parent comes before its " "children", 0), { OPTION_CALLBACK, 'g', "reflog", &reflog_base, "<n>[,<base>]", "show <n> most recent ref-log entries starting at " "base", PARSE_OPT_OPTARG | PARSE_OPT_LITERAL_ARGHELP, parse_reflog_param }, OPT_END() }; git_config(git_show_branch_config, NULL); if (showbranch_use_color == -1) showbranch_use_color = git_use_color_default; /* If nothing is specified, try the default first */ if (ac == 1 && default_num) { ac = default_num; av = default_arg; } ac = parse_options(ac, av, prefix, builtin_show_branch_options, show_branch_usage, PARSE_OPT_STOP_AT_NON_OPTION); if (all_heads) all_remotes = 1; if (extra || reflog) { /* "listing" mode is incompatible with * independent nor merge-base modes. */ if (independent || merge_base) usage_with_options(show_branch_usage, builtin_show_branch_options); if (reflog && ((0 < extra) || all_heads || all_remotes)) /* * Asking for --more in reflog mode does not * make sense. --list is Ok. * * Also --all and --remotes do not make sense either. */ die("--reflog is incompatible with --all, --remotes, " "--independent or --merge-base"); } /* If nothing is specified, show all branches by default */ if (ac + all_heads + all_remotes == 0) all_heads = 1; if (reflog) { unsigned char sha1[20]; char nth_desc[256]; char *ref; int base = 0; if (ac == 0) { static const char *fake_av[2]; const char *refname; refname = resolve_ref("HEAD", sha1, 1, NULL); fake_av[0] = xstrdup(refname); fake_av[1] = NULL; av = fake_av; ac = 1; } if (ac != 1) die("--reflog option needs one branch name"); if (MAX_REVS < reflog) die("Only %d entries can be shown at one time.", MAX_REVS); if (!dwim_ref(*av, strlen(*av), sha1, &ref)) die("No such ref %s", *av); /* Has the base been specified? */ if (reflog_base) { char *ep; base = strtoul(reflog_base, &ep, 10); if (*ep) { /* Ah, that is a date spec... */ unsigned long at; at = approxidate(reflog_base); read_ref_at(ref, at, -1, sha1, NULL, NULL, NULL, &base); } } for (i = 0; i < reflog; i++) { char *logmsg, *m; const char *msg; unsigned long timestamp; int tz; if (read_ref_at(ref, 0, base+i, sha1, &logmsg, ×tamp, &tz, NULL)) { reflog = i; break; } msg = strchr(logmsg, '\t'); if (!msg) msg = "(none)"; else msg++; m = xmalloc(strlen(msg) + 200); sprintf(m, "(%s) %s", show_date(timestamp, tz, 1), msg); reflog_msg[i] = m; free(logmsg); sprintf(nth_desc, "%s@{%d}", *av, base+i); append_ref(nth_desc, sha1, 1); } } else if (all_heads + all_remotes) snarf_refs(all_heads, all_remotes); else { while (0 < ac) { append_one_rev(*av); ac--; av++; } } head_p = resolve_ref("HEAD", head_sha1, 1, NULL); if (head_p) { head_len = strlen(head_p); memcpy(head, head_p, head_len + 1); } else { head_len = 0; head[0] = 0; } if (with_current_branch && head_p) { int has_head = 0; for (i = 0; !has_head && i < ref_name_cnt; i++) { /* We are only interested in adding the branch * HEAD points at. */ if (rev_is_head(head, head_len, ref_name[i], head_sha1, NULL)) has_head++; } if (!has_head) { int offset = !prefixcmp(head, "refs/heads/") ? 11 : 0; append_one_rev(head + offset); } } if (!ref_name_cnt) { fprintf(stderr, "No revs to be shown.\n"); exit(0); } for (num_rev = 0; ref_name[num_rev]; num_rev++) { unsigned char revkey[20]; unsigned int flag = 1u << (num_rev + REV_SHIFT); if (MAX_REVS <= num_rev) die("cannot handle more than %d revs.", MAX_REVS); if (get_sha1(ref_name[num_rev], revkey)) die("'%s' is not a valid ref.", ref_name[num_rev]); commit = lookup_commit_reference(revkey); if (!commit) die("cannot find commit %s (%s)", ref_name[num_rev], revkey); parse_commit(commit); mark_seen(commit, &seen); /* rev#0 uses bit REV_SHIFT, rev#1 uses bit REV_SHIFT+1, * and so on. REV_SHIFT bits from bit 0 are used for * internal bookkeeping. */ commit->object.flags |= flag; if (commit->object.flags == flag) commit_list_insert_by_date(commit, &list); rev[num_rev] = commit; } for (i = 0; i < num_rev; i++) rev_mask[i] = rev[i]->object.flags; if (0 <= extra) join_revs(&list, &seen, num_rev, extra); commit_list_sort_by_date(&seen); if (merge_base) return show_merge_base(seen, num_rev); if (independent) return show_independent(rev, num_rev, ref_name, rev_mask); /* Show list; --more=-1 means list-only */ if (1 < num_rev || extra < 0) { for (i = 0; i < num_rev; i++) { int j; int is_head = rev_is_head(head, head_len, ref_name[i], head_sha1, rev[i]->object.sha1); if (extra < 0) printf("%c [%s] ", is_head ? '*' : ' ', ref_name[i]); else { for (j = 0; j < i; j++) putchar(' '); printf("%s%c%s [%s] ", get_color_code(i % COLUMN_COLORS_MAX), is_head ? '*' : '!', get_color_reset_code(), ref_name[i]); } if (!reflog) { /* header lines never need name */ show_one_commit(rev[i], 1); } else puts(reflog_msg[i]); if (is_head) head_at = i; } if (0 <= extra) { for (i = 0; i < num_rev; i++) putchar('-'); putchar('\n'); } } if (extra < 0) exit(0); /* Sort topologically */ sort_in_topological_order(&seen, lifo); /* Give names to commits */ if (!sha1_name && !no_name) name_commits(seen, rev, ref_name, num_rev); all_mask = ((1u << (REV_SHIFT + num_rev)) - 1); all_revs = all_mask & ~((1u << REV_SHIFT) - 1); while (seen) { struct commit *commit = pop_one_commit(&seen); int this_flag = commit->object.flags; int is_merge_point = ((this_flag & all_revs) == all_revs); shown_merge_point |= is_merge_point; if (1 < num_rev) { int is_merge = !!(commit->parents && commit->parents->next); if (topics && !is_merge_point && (this_flag & (1u << REV_SHIFT))) continue; if (dense && is_merge && omit_in_dense(commit, rev, num_rev)) continue; for (i = 0; i < num_rev; i++) { int mark; if (!(this_flag & (1u << (i + REV_SHIFT)))) mark = ' '; else if (is_merge) mark = '-'; else if (i == head_at) mark = '*'; else mark = '+'; printf("%s%c%s", get_color_code(i % COLUMN_COLORS_MAX), mark, get_color_reset_code()); } putchar(' '); } show_one_commit(commit, no_name); if (shown_merge_point && --extra < 0) break; } return 0; }
static int find_common(struct fetch_negotiator *negotiator, struct fetch_pack_args *args, int fd[2], struct object_id *result_oid, struct ref *refs) { int fetching; int count = 0, flushes = 0, flush_at = INITIAL_FLUSH, retval; const struct object_id *oid; unsigned in_vain = 0; int got_continue = 0; int got_ready = 0; struct strbuf req_buf = STRBUF_INIT; size_t state_len = 0; if (args->stateless_rpc && multi_ack == 1) die(_("--stateless-rpc requires multi_ack_detailed")); if (!args->no_dependents) { mark_tips(negotiator, args->negotiation_tips); for_each_cached_alternate(negotiator, insert_one_alternate_object); } fetching = 0; for ( ; refs ; refs = refs->next) { struct object_id *remote = &refs->old_oid; const char *remote_hex; struct object *o; /* * If that object is complete (i.e. it is an ancestor of a * local ref), we tell them we have it but do not have to * tell them about its ancestors, which they already know * about. * * We use lookup_object here because we are only * interested in the case we *know* the object is * reachable and we have already scanned it. * * Do this only if args->no_dependents is false (if it is true, * we cannot trust the object flags). */ if (!args->no_dependents && ((o = lookup_object(the_repository, remote->hash)) != NULL) && (o->flags & COMPLETE)) { continue; } remote_hex = oid_to_hex(remote); if (!fetching) { struct strbuf c = STRBUF_INIT; if (multi_ack == 2) strbuf_addstr(&c, " multi_ack_detailed"); if (multi_ack == 1) strbuf_addstr(&c, " multi_ack"); if (no_done) strbuf_addstr(&c, " no-done"); if (use_sideband == 2) strbuf_addstr(&c, " side-band-64k"); if (use_sideband == 1) strbuf_addstr(&c, " side-band"); if (args->deepen_relative) strbuf_addstr(&c, " deepen-relative"); if (args->use_thin_pack) strbuf_addstr(&c, " thin-pack"); if (args->no_progress) strbuf_addstr(&c, " no-progress"); if (args->include_tag) strbuf_addstr(&c, " include-tag"); if (prefer_ofs_delta) strbuf_addstr(&c, " ofs-delta"); if (deepen_since_ok) strbuf_addstr(&c, " deepen-since"); if (deepen_not_ok) strbuf_addstr(&c, " deepen-not"); if (agent_supported) strbuf_addf(&c, " agent=%s", git_user_agent_sanitized()); if (args->filter_options.choice) strbuf_addstr(&c, " filter"); packet_buf_write(&req_buf, "want %s%s\n", remote_hex, c.buf); strbuf_release(&c); } else packet_buf_write(&req_buf, "want %s\n", remote_hex); fetching++; } if (!fetching) { strbuf_release(&req_buf); packet_flush(fd[1]); return 1; } if (is_repository_shallow(the_repository)) write_shallow_commits(&req_buf, 1, NULL); if (args->depth > 0) packet_buf_write(&req_buf, "deepen %d", args->depth); if (args->deepen_since) { timestamp_t max_age = approxidate(args->deepen_since); packet_buf_write(&req_buf, "deepen-since %"PRItime, max_age); } if (args->deepen_not) { int i; for (i = 0; i < args->deepen_not->nr; i++) { struct string_list_item *s = args->deepen_not->items + i; packet_buf_write(&req_buf, "deepen-not %s", s->string); } } if (server_supports_filtering && args->filter_options.choice) packet_buf_write(&req_buf, "filter %s", args->filter_options.filter_spec); packet_buf_flush(&req_buf); state_len = req_buf.len; if (args->deepen) { char *line; const char *arg; struct object_id oid; send_request(args, fd[1], &req_buf); while ((line = packet_read_line(fd[0], NULL))) { if (skip_prefix(line, "shallow ", &arg)) { if (get_oid_hex(arg, &oid)) die(_("invalid shallow line: %s"), line); register_shallow(the_repository, &oid); continue; } if (skip_prefix(line, "unshallow ", &arg)) { if (get_oid_hex(arg, &oid)) die(_("invalid unshallow line: %s"), line); if (!lookup_object(the_repository, oid.hash)) die(_("object not found: %s"), line); /* make sure that it is parsed as shallow */ if (!parse_object(the_repository, &oid)) die(_("error in object: %s"), line); if (unregister_shallow(&oid)) die(_("no shallow found: %s"), line); continue; } die(_("expected shallow/unshallow, got %s"), line); } } else if (!args->stateless_rpc) send_request(args, fd[1], &req_buf); if (!args->stateless_rpc) { /* If we aren't using the stateless-rpc interface * we don't need to retain the headers. */ strbuf_setlen(&req_buf, 0); state_len = 0; } flushes = 0; retval = -1; if (args->no_dependents) goto done; while ((oid = negotiator->next(negotiator))) { packet_buf_write(&req_buf, "have %s\n", oid_to_hex(oid)); print_verbose(args, "have %s", oid_to_hex(oid)); in_vain++; if (flush_at <= ++count) { int ack; packet_buf_flush(&req_buf); send_request(args, fd[1], &req_buf); strbuf_setlen(&req_buf, state_len); flushes++; flush_at = next_flush(args->stateless_rpc, count); /* * We keep one window "ahead" of the other side, and * will wait for an ACK only on the next one */ if (!args->stateless_rpc && count == INITIAL_FLUSH) continue; consume_shallow_list(args, fd[0]); do { ack = get_ack(fd[0], result_oid); if (ack) print_verbose(args, _("got %s %d %s"), "ack", ack, oid_to_hex(result_oid)); switch (ack) { case ACK: flushes = 0; multi_ack = 0; retval = 0; goto done; case ACK_common: case ACK_ready: case ACK_continue: { struct commit *commit = lookup_commit(the_repository, result_oid); int was_common; if (!commit) die(_("invalid commit %s"), oid_to_hex(result_oid)); was_common = negotiator->ack(negotiator, commit); if (args->stateless_rpc && ack == ACK_common && !was_common) { /* We need to replay the have for this object * on the next RPC request so the peer knows * it is in common with us. */ const char *hex = oid_to_hex(result_oid); packet_buf_write(&req_buf, "have %s\n", hex); state_len = req_buf.len; /* * Reset in_vain because an ack * for this commit has not been * seen. */ in_vain = 0; } else if (!args->stateless_rpc || ack != ACK_common) in_vain = 0; retval = 0; got_continue = 1; if (ack == ACK_ready) got_ready = 1; break; } } } while (ack); flushes--; if (got_continue && MAX_IN_VAIN < in_vain) { print_verbose(args, _("giving up")); break; /* give up */ } if (got_ready) break; } } done: if (!got_ready || !no_done) { packet_buf_write(&req_buf, "done\n"); send_request(args, fd[1], &req_buf); } print_verbose(args, _("done")); if (retval != 0) { multi_ack = 0; flushes++; } strbuf_release(&req_buf); if (!got_ready || !no_done) consume_shallow_list(args, fd[0]); while (flushes || multi_ack) { int ack = get_ack(fd[0], result_oid); if (ack) { print_verbose(args, _("got %s (%d) %s"), "ack", ack, oid_to_hex(result_oid)); if (ack == ACK) return 0; multi_ack = 1; continue; } flushes--; } /* it is no error to fetch into a completely empty repo */ return count ? retval : 0; }