static bool check_type(SordModel* model, const URIs* uris, const SordNode* node, const SordNode* type) { if (sord_node_equals(type, uris->rdfs_Resource) || sord_node_equals(type, uris->owl_Thing)) { return true; } if (sord_node_get_type(node) == SORD_LITERAL) { if (sord_node_equals(type, uris->rdfs_Literal)) { return true; } else if (sord_node_equals(type, uris->rdf_PlainLiteral)) { return !sord_node_get_language(node); } else { return literal_is_valid(model, uris, node, type); } } else if (sord_node_get_type(node) == SORD_URI) { if (sord_node_equals(type, uris->foaf_Document)) { return true; // Questionable... } else if (is_descendant_of( model, uris, type, uris->xsd_anyURI, uris->owl_onDatatype)) { /* Type is any URI and this is a URI, so pass. Restrictions on anyURI subtypes are not currently checked (very uncommon). */ return true; // Type is anyURI, and this is a URI } else { SordIter* t = sord_search(model, node, uris->rdf_type, NULL, NULL); for (; !sord_iter_end(t); sord_iter_next(t)) { if (is_descendant_of(model, uris, sord_iter_get_node(t, SORD_OBJECT), type, uris->rdfs_subClassOf)) { sord_iter_free(t); return true; } } sord_iter_free(t); return false; } } else { return true; // Blanks often lack explicit types, ignore } return false; }
static bool is_descendant_of(SordModel* model, const URIs* uris, const SordNode* child, const SordNode* parent, const SordNode* pred) { if (!child) { return false; } else if (sord_node_equals(child, parent) || sord_ask(model, child, uris->owl_equivalentClass, parent, NULL)) { return true; } SordIter* i = sord_search(model, child, pred, NULL, NULL); for (; !sord_iter_end(i); sord_iter_next(i)) { const SordNode* o = sord_iter_get_node(i, SORD_OBJECT); if (sord_node_equals(child, o)) { continue; // Weird class is explicitly a descendent of itself } if (is_descendant_of(model, uris, o, parent, pred)) { sord_iter_free(i); return true; } } sord_iter_free(i); return false; }
static int append_ref(const char *refname, const unsigned char *sha1, int flags, void *cb_data) { struct ref_list *ref_list = (struct ref_list*)(cb_data); struct ref_item *newitem; struct commit *commit; int kind; int len; /* Detect kind */ if (!prefixcmp(refname, "refs/heads/")) { kind = REF_LOCAL_BRANCH; refname += 11; } else if (!prefixcmp(refname, "refs/remotes/")) { kind = REF_REMOTE_BRANCH; refname += 13; } else return 0; commit = lookup_commit_reference_gently(sha1, 1); if (!commit) return error("branch '%s' does not point at a commit", refname); /* Filter with with_commit if specified */ if (!is_descendant_of(commit, ref_list->with_commit)) return 0; /* Don't add types the caller doesn't want */ if ((kind & ref_list->kinds) == 0) return 0; if (merge_filter != NO_FILTER) add_pending_object(&ref_list->revs, (struct object *)commit, refname); /* Resize buffer */ if (ref_list->index >= ref_list->alloc) { ref_list->alloc = alloc_nr(ref_list->alloc); ref_list->list = xrealloc(ref_list->list, ref_list->alloc * sizeof(struct ref_item)); } /* Record the new item */ newitem = &(ref_list->list[ref_list->index++]); newitem->name = xstrdup(refname); newitem->kind = kind; newitem->commit = commit; len = strlen(newitem->name); if (len > ref_list->maxwidth) ref_list->maxwidth = len; return 0; }
static void print_ref_list(int kinds, int detached, int verbose, int abbrev, struct commit_list *with_commit) { int i; struct ref_list ref_list; struct commit *head_commit = lookup_commit_reference_gently(head_sha1, 1); memset(&ref_list, 0, sizeof(ref_list)); ref_list.kinds = kinds; ref_list.with_commit = with_commit; if (merge_filter != NO_FILTER) init_revisions(&ref_list.revs, NULL); for_each_ref(append_ref, &ref_list); if (merge_filter != NO_FILTER) { struct commit *filter; filter = lookup_commit_reference_gently(merge_filter_ref, 0); filter->object.flags |= UNINTERESTING; add_pending_object(&ref_list.revs, (struct object *) filter, ""); ref_list.revs.limited = 1; prepare_revision_walk(&ref_list.revs); if (verbose) ref_list.maxwidth = calc_maxwidth(&ref_list); } qsort(ref_list.list, ref_list.index, sizeof(struct ref_item), ref_cmp); detached = (detached && (kinds & REF_LOCAL_BRANCH)); if (detached && head_commit && is_descendant_of(head_commit, with_commit)) { struct ref_item item; item.name = xstrdup("(no branch)"); item.kind = REF_LOCAL_BRANCH; item.commit = head_commit; if (strlen(item.name) > ref_list.maxwidth) ref_list.maxwidth = strlen(item.name); print_ref_item(&item, ref_list.maxwidth, verbose, abbrev, 1); free(item.name); } for (i = 0; i < ref_list.index; i++) { int current = !detached && (ref_list.list[i].kind == REF_LOCAL_BRANCH) && !strcmp(ref_list.list[i].name, head); print_ref_item(&ref_list.list[i], ref_list.maxwidth, verbose, abbrev, current); } free_ref_list(&ref_list); }
static void show_detached(struct ref_list *ref_list) { struct commit *head_commit = lookup_commit_reference_gently(head_sha1, 1); if (head_commit && is_descendant_of(head_commit, ref_list->with_commit)) { struct ref_item item; item.name = get_head_description(); item.width = utf8_strwidth(item.name); item.kind = REF_LOCAL_BRANCH; item.dest = NULL; item.commit = head_commit; if (item.width > ref_list->maxwidth) ref_list->maxwidth = item.width; print_ref_item(&item, ref_list->maxwidth, ref_list->verbose, ref_list->abbrev, 1, ""); free(item.name); } }
static void show_detached(struct ref_list *ref_list) { struct commit *head_commit = lookup_commit_reference_gently(head_sha1, 1); if (head_commit && is_descendant_of(head_commit, ref_list->with_commit)) { struct ref_item item; item.name = xstrdup("(no branch)"); item.len = strlen(item.name); item.kind = REF_LOCAL_BRANCH; item.dest = NULL; item.commit = head_commit; if (item.len > ref_list->maxwidth) ref_list->maxwidth = item.len; print_ref_item(&item, ref_list->maxwidth, ref_list->verbose, ref_list->abbrev, 1, ""); free(item.name); } }
int cmd_pull(int argc, const char **argv, const char *prefix) { const char *repo, **refspecs; struct oid_array merge_heads = OID_ARRAY_INIT; struct object_id orig_head, curr_head; struct object_id rebase_fork_point; int autostash; if (!getenv("GIT_REFLOG_ACTION")) set_reflog_message(argc, argv); git_config(git_pull_config, NULL); argc = parse_options(argc, argv, prefix, pull_options, pull_usage, 0); parse_repo_refspecs(argc, argv, &repo, &refspecs); if (!opt_ff) opt_ff = xstrdup_or_null(config_get_ff()); if (opt_rebase < 0) opt_rebase = config_get_rebase(); if (read_cache_unmerged()) die_resolve_conflict("pull"); if (file_exists(git_path_merge_head(the_repository))) die_conclude_merge(); if (get_oid("HEAD", &orig_head)) oidclr(&orig_head); if (!opt_rebase && opt_autostash != -1) die(_("--[no-]autostash option is only valid with --rebase.")); autostash = config_autostash; if (opt_rebase) { if (opt_autostash != -1) autostash = opt_autostash; if (is_null_oid(&orig_head) && !is_cache_unborn()) die(_("Updating an unborn branch with changes added to the index.")); if (!autostash) require_clean_work_tree(N_("pull with rebase"), _("please commit or stash them."), 1, 0); if (get_rebase_fork_point(&rebase_fork_point, repo, *refspecs)) oidclr(&rebase_fork_point); } if (run_fetch(repo, refspecs)) return 1; if (opt_dry_run) return 0; if (get_oid("HEAD", &curr_head)) oidclr(&curr_head); if (!is_null_oid(&orig_head) && !is_null_oid(&curr_head) && !oideq(&orig_head, &curr_head)) { /* * The fetch involved updating the current branch. * * The working tree and the index file are still based on * orig_head commit, but we are merging into curr_head. * Update the working tree to match curr_head. */ warning(_("fetch updated the current branch head.\n" "fast-forwarding your working tree from\n" "commit %s."), oid_to_hex(&orig_head)); if (checkout_fast_forward(&orig_head, &curr_head, 0)) die(_("Cannot fast-forward your working tree.\n" "After making sure that you saved anything precious from\n" "$ git diff %s\n" "output, run\n" "$ git reset --hard\n" "to recover."), oid_to_hex(&orig_head)); } get_merge_heads(&merge_heads); if (!merge_heads.nr) die_no_merge_candidates(repo, refspecs); if (is_null_oid(&orig_head)) { if (merge_heads.nr > 1) die(_("Cannot merge multiple branches into empty head.")); return pull_into_void(merge_heads.oid, &curr_head); } if (opt_rebase && merge_heads.nr > 1) die(_("Cannot rebase onto multiple branches.")); if (opt_rebase) { int ret = 0; if ((recurse_submodules == RECURSE_SUBMODULES_ON || recurse_submodules == RECURSE_SUBMODULES_ON_DEMAND) && submodule_touches_in_range(&rebase_fork_point, &curr_head)) die(_("cannot rebase with locally recorded submodule modifications")); if (!autostash) { struct commit_list *list = NULL; struct commit *merge_head, *head; head = lookup_commit_reference(the_repository, &orig_head); commit_list_insert(head, &list); merge_head = lookup_commit_reference(the_repository, &merge_heads.oid[0]); if (is_descendant_of(merge_head, list)) { /* we can fast-forward this without invoking rebase */ opt_ff = "--ff-only"; ret = run_merge(); } } ret = run_rebase(&curr_head, merge_heads.oid, &rebase_fork_point); if (!ret && (recurse_submodules == RECURSE_SUBMODULES_ON || recurse_submodules == RECURSE_SUBMODULES_ON_DEMAND)) ret = rebase_submodules(); return ret; } else { int ret = run_merge(); if (!ret && (recurse_submodules == RECURSE_SUBMODULES_ON || recurse_submodules == RECURSE_SUBMODULES_ON_DEMAND)) ret = update_submodules(); return ret; } }
static int append_ref(const char *refname, const unsigned char *sha1, int flags, void *cb_data) { struct append_ref_cb *cb = (struct append_ref_cb *)(cb_data); struct ref_list *ref_list = cb->ref_list; struct ref_item *newitem; struct commit *commit; int kind, i; const char *prefix, *orig_refname = refname; static struct { int kind; const char *prefix; int pfxlen; } ref_kind[] = { { REF_LOCAL_BRANCH, "refs/heads/", 11 }, { REF_REMOTE_BRANCH, "refs/remotes/", 13 }, }; /* Detect kind */ for (i = 0; i < ARRAY_SIZE(ref_kind); i++) { prefix = ref_kind[i].prefix; if (strncmp(refname, prefix, ref_kind[i].pfxlen)) continue; kind = ref_kind[i].kind; refname += ref_kind[i].pfxlen; break; } if (ARRAY_SIZE(ref_kind) <= i) return 0; /* Don't add types the caller doesn't want */ if ((kind & ref_list->kinds) == 0) return 0; if (!match_patterns(cb->pattern, refname)) return 0; commit = NULL; if (ref_list->verbose || ref_list->with_commit || merge_filter != NO_FILTER) { commit = lookup_commit_reference_gently(sha1, 1); if (!commit) { cb->ret = error(_("branch '%s' does not point at a commit"), refname); return 0; } /* Filter with with_commit if specified */ if (!is_descendant_of(commit, ref_list->with_commit)) return 0; if (merge_filter != NO_FILTER) add_pending_object(&ref_list->revs, (struct object *)commit, refname); } ALLOC_GROW(ref_list->list, ref_list->index + 1, ref_list->alloc); /* Record the new item */ newitem = &(ref_list->list[ref_list->index++]); newitem->name = xstrdup(refname); newitem->kind = kind; newitem->commit = commit; newitem->width = utf8_strwidth(refname); newitem->dest = resolve_symref(orig_refname, prefix); /* adjust for "remotes/" */ if (newitem->kind == REF_REMOTE_BRANCH && ref_list->kinds != REF_REMOTE_BRANCH) newitem->width += 8; if (newitem->width > ref_list->maxwidth) ref_list->maxwidth = newitem->width; return 0; }
static int check_properties(SordModel* model, URIs* uris) { int st = 0; SordIter* i = sord_begin(model); for (; !sord_iter_end(i); sord_iter_next(i)) { SordQuad quad; sord_iter_get(i, quad); const SordNode* subj = quad[SORD_SUBJECT]; const SordNode* pred = quad[SORD_PREDICATE]; const SordNode* obj = quad[SORD_OBJECT]; bool is_any_property = false; SordIter* t = sord_search(model, pred, uris->rdf_type, NULL, NULL); for (; !sord_iter_end(t); sord_iter_next(t)) { if (is_descendant_of(model, uris, sord_iter_get_node(t, SORD_OBJECT), uris->rdf_Property, uris->rdfs_subClassOf)) { is_any_property = true; break; } } sord_iter_free(t); const bool is_ObjectProperty = sord_ask( model, pred, uris->rdf_type, uris->owl_ObjectProperty, 0); const bool is_FunctionalProperty = sord_ask( model, pred, uris->rdf_type, uris->owl_FunctionalProperty, 0); const bool is_InverseFunctionalProperty = sord_ask( model, pred, uris->rdf_type, uris->owl_InverseFunctionalProperty, 0); const bool is_DatatypeProperty = sord_ask( model, pred, uris->rdf_type, uris->owl_DatatypeProperty, 0); if (!is_any_property) { st = error("Use of undefined property", quad); } if (!sord_ask(model, pred, uris->rdfs_label, NULL, NULL)) { st = errorf("Property <%s> has no label\n", sord_node_get_string(pred)); } if (is_DatatypeProperty && sord_node_get_type(obj) != SORD_LITERAL) { st = error("Datatype property with non-literal value", quad); } if (is_ObjectProperty && sord_node_get_type(obj) == SORD_LITERAL) { st = error("Object property with literal value", quad); } if (is_FunctionalProperty && sord_count(model, subj, pred, NULL, NULL) > 1) { st = error("Functional property with several objects", quad); } if (is_InverseFunctionalProperty && sord_count(model, NULL, pred, obj, NULL) > 1) { st = error("Inverse functional property with several subjects", quad); } if (sord_node_equals(pred, uris->rdf_type) && !sord_ask(model, obj, uris->rdf_type, uris->rdfs_Class, NULL) && !sord_ask(model, obj, uris->rdf_type, uris->owl_Class, NULL)) { st = error("Type is not a rdfs:Class or owl:Class", quad); } if (sord_node_get_type(obj) == SORD_LITERAL && !literal_is_valid(model, uris, obj, sord_node_get_datatype(obj))) { st = error("Literal does not match datatype", quad); } SordIter* r = sord_search(model, pred, uris->rdfs_range, NULL, NULL); for (; !sord_iter_end(r); sord_iter_next(r)) { const SordNode* range = sord_iter_get_node(r, SORD_OBJECT); if (!check_type(model, uris, obj, range)) { st = error("Object not in property range", quad); fprintf(stderr, "note: Range is <%s>\n", sord_node_get_string(range)); } } sord_iter_free(r); SordIter* d = sord_search(model, pred, uris->rdfs_domain, NULL, NULL); if (d) { const SordNode* domain = sord_iter_get_node(d, SORD_OBJECT); if (!check_type(model, uris, subj, domain)) { st = error("Subject not in property domain", quad); fprintf(stderr, "note: Domain is <%s>\n", sord_node_get_string(domain)); } sord_iter_free(d); } } sord_iter_free(i); return st; }
static bool literal_is_valid(SordModel* model, const URIs* uris, const SordNode* literal, const SordNode* type) { if (!type) { return true; } /* Check that literal data is related to required type. We don't do a strict subtype check here because e.g. an xsd:decimal might be a valid xsd:unsignedInt, which the pattern checks will verify, but if the literal type is not related to the required type at all (e.g. xsd:decimal and xsd:string) there is a problem. */ const SordNode* datatype = sord_node_get_datatype(literal); if (datatype && datatype != type) { if (!is_descendant_of( model, uris, datatype, type, uris->owl_onDatatype) && !is_descendant_of( model, uris, type, datatype, uris->owl_onDatatype)) { errorf("Literal `%s' datatype <%s> is not compatible with <%s>\n", sord_node_get_string(literal), sord_node_get_string(datatype), sord_node_get_string(type)); return false; } } // Find restrictions list SordIter* rs = sord_search(model, type, uris->owl_withRestrictions, 0, 0); if (sord_iter_end(rs)) { return true; // No restrictions } // Walk list, checking each restriction const SordNode* head = sord_iter_get_node(rs, SORD_OBJECT); while (head) { SordIter* f = sord_search(model, head, uris->rdf_first, 0, 0); if (!f) { break; // Reached end of restrictions list without failure } // Check this restriction const bool good = check_restriction( model, uris, literal, type, sord_iter_get_node(f, SORD_OBJECT)); sord_iter_free(f); if (!good) { sord_iter_free(rs); return false; // Failed, literal is invalid } // Seek to next list node SordIter* n = sord_search(model, head, uris->rdf_rest, 0, 0); head = n ? sord_iter_get_node(n, SORD_OBJECT) : NULL; sord_iter_free(n); } sord_iter_free(rs); SordIter* s = sord_search(model, type, uris->owl_onDatatype, 0, 0); if (s) { const SordNode* super = sord_iter_get_node(s, SORD_OBJECT); const bool good = literal_is_valid(model, uris, literal, super); sord_iter_free(s); return good; // Match iff literal also matches supertype } return true; // Matches top level type }
static bool check_restriction(SordModel* model, const URIs* uris, const SordNode* literal, const SordNode* type, const SordNode* restriction) { size_t len = 0; const char* str = (const char*)sord_node_get_string_counted(literal, &len); ++n_restrictions; // Check xsd:pattern SordIter* p = sord_search(model, restriction, uris->xsd_pattern, 0, 0); if (p) { const SordNode* pat = sord_iter_get_node(p, SORD_OBJECT); const bool good = regexp_match(sord_node_get_string(pat), str); if (!good) { fprintf(stderr, "`%s' does not match <%s> pattern `%s'\n", sord_node_get_string(literal), sord_node_get_string(type), sord_node_get_string(pat)); } sord_iter_free(p); return good; } /* We'll do some comparison tricks for xsd:decimal types, where lexicographical comparison would be incorrect. Note that if the literal's type is a descendant of xsd:decimal, we'll end up checking it against the xsd:decimal pattern so there's no need to validate digits here. At worst we'll get a false positive but it will fail later. */ const bool is_decimal = is_descendant_of( model, uris, type, uris->xsd_decimal, uris->owl_onDatatype); // Check xsd:minInclusive SordIter* l = sord_search(model, restriction, uris->xsd_minInclusive, 0, 0); if (l) { const SordNode* lower = sord_iter_get_node(l, SORD_OBJECT); size_t lower_len = 0; const char* lower_str = (const char*)sord_node_get_string_counted(lower, &lower_len); bool good = false; if (!is_decimal || len == lower_len) { // Not decimal, or equal lengths, strcmp good = (strcmp(str, lower_str) >= 0); } else { // Decimal with different length, only good if longer than the min good = (len > lower_len); } if (!good) { fprintf(stderr, "`%s' is not >= <%s> minimum `%s'\n", sord_node_get_string(literal), sord_node_get_string(type), sord_node_get_string(lower)); } sord_iter_free(l); return good; } // Check xsd:maxInclusive SordIter* u = sord_search(model, restriction, uris->xsd_maxInclusive, 0, 0); if (u) { const SordNode* upper = sord_iter_get_node(u, SORD_OBJECT); size_t upper_len = 0; const char* upper_str = (const char*)sord_node_get_string_counted(upper, &upper_len); bool good = false; if (!is_decimal || len == upper_len) { // Not decimal, or equal lengths, strcmp good = (strcmp(str, upper_str) <= 0); } else { // Decimal with different length, only good if shorter than the max good = (len < upper_len); } if (!good) { fprintf(stderr, "`%s' is not <= <%s> maximum `%s'\n", sord_node_get_string(literal), sord_node_get_string(type), sord_node_get_string(upper)); } sord_iter_free(u); return good; } --n_restrictions; return true; // Unknown restriction, be quietly tolerant }