int git_graph_ahead_behind(size_t *ahead, size_t *behind, git_repository *repo, const git_oid *one, const git_oid *two) { git_revwalk *walk; git_vector list; struct git_commit_list *result = NULL; git_commit_list_node *commit1, *commit2; void *contents[1]; if (git_revwalk_new(&walk, repo) < 0) return -1; commit2 = git_revwalk__commit_lookup(walk, two); if (commit2 == NULL) goto on_error; /* This is just one value, so we can do it on the stack */ memset(&list, 0x0, sizeof(git_vector)); contents[0] = commit2; list.length = 1; list.contents = contents; commit1 = git_revwalk__commit_lookup(walk, one); if (commit1 == NULL) goto on_error; if (git_merge__bases_many(&result, walk, commit1, &list) < 0) goto on_error; if (ahead_behind(commit1, commit2, ahead, behind) < 0) goto on_error; if (!result) { git_revwalk_free(walk); return GIT_ENOTFOUND; } git_commit_list_free(&result); git_revwalk_free(walk); return 0; on_error: git_revwalk_free(walk); return -1; }
static int push_commit(git_revwalk *walk, const git_oid *oid, int uninteresting, int from_glob) { git_oid commit_id; int error; git_object *obj, *oobj; git_commit_list_node *commit; git_commit_list *list; if ((error = git_object_lookup(&oobj, walk->repo, oid, GIT_OBJ_ANY)) < 0) return error; error = git_object_peel(&obj, oobj, GIT_OBJ_COMMIT); git_object_free(oobj); if (error == GIT_ENOTFOUND || error == GIT_EINVALIDSPEC || error == GIT_EPEEL) { /* If this comes from e.g. push_glob("tags"), ignore this */ if (from_glob) return 0; giterr_set(GITERR_INVALID, "Object is not a committish"); return -1; } if (error < 0) return error; git_oid_cpy(&commit_id, git_object_id(obj)); git_object_free(obj); commit = git_revwalk__commit_lookup(walk, &commit_id); if (commit == NULL) return -1; /* error already reported by failed lookup */ /* A previous hide already told us we don't want this commit */ if (commit->uninteresting) return 0; if (uninteresting) walk->did_hide = 1; else walk->did_push = 1; commit->uninteresting = uninteresting; list = walk->user_input; if (git_commit_list_insert(commit, &list) == NULL) { giterr_set_oom(); return -1; } walk->user_input = list; return 0; }
static int commit_quick_parse(git_revwalk *walk, git_commit_list_node *commit, git_rawobj *raw) { const size_t parent_len = strlen("parent ") + GIT_OID_HEXSZ + 1; unsigned char *buffer = raw->data; unsigned char *buffer_end = buffer + raw->len; unsigned char *parents_start, *committer_start; int i, parents = 0; int commit_time; buffer += strlen("tree ") + GIT_OID_HEXSZ + 1; parents_start = buffer; while (buffer + parent_len < buffer_end && memcmp(buffer, "parent ", strlen("parent ")) == 0) { parents++; buffer += parent_len; } commit->parents = alloc_parents(walk, commit, parents); GITERR_CHECK_ALLOC(commit->parents); buffer = parents_start; for (i = 0; i < parents; ++i) { git_oid oid; if (git_oid_fromstr(&oid, (char *)buffer + strlen("parent ")) < 0) return -1; commit->parents[i] = git_revwalk__commit_lookup(walk, &oid); if (commit->parents[i] == NULL) return -1; buffer += parent_len; } commit->out_degree = (unsigned short)parents; if ((committer_start = buffer = memchr(buffer, '\n', buffer_end - buffer)) == NULL) return commit_error(commit, "object is corrupted"); buffer++; if ((buffer = memchr(buffer, '\n', buffer_end - buffer)) == NULL) return commit_error(commit, "object is corrupted"); /* Skip trailing spaces */ while (buffer > committer_start && git__isspace(*buffer)) buffer--; /* Seek for the begining of the pack of digits */ while (buffer > committer_start && git__isdigit(*buffer)) buffer--; /* Skip potential timezone offset */ if ((buffer > committer_start) && (*buffer == '+' || *buffer == '-')) { buffer--; while (buffer > committer_start && git__isspace(*buffer)) buffer--; while (buffer > committer_start && git__isdigit(*buffer)) buffer--; } if ((buffer == committer_start) || (git__strtol32(&commit_time, (char *)(buffer + 1), NULL, 10) < 0)) return commit_error(commit, "cannot parse commit time"); commit->time = (time_t)commit_time; commit->parsed = 1; return 0; }