/* * Return true iff the specified reflog entry should be expired. */ static int should_expire_reflog_ent(struct object_id *ooid, struct object_id *noid, const char *email, timestamp_t timestamp, int tz, const char *message, void *cb_data) { struct expire_reflog_policy_cb *cb = cb_data; struct commit *old_commit, *new_commit; if (timestamp < cb->cmd.expire_total) return 1; old_commit = new_commit = NULL; if (cb->cmd.stalefix && (!keep_entry(&old_commit, ooid) || !keep_entry(&new_commit, noid))) return 1; if (timestamp < cb->cmd.expire_unreachable) { if (cb->unreachable_expire_kind == UE_ALWAYS) return 1; if (unreachable(cb, old_commit, ooid) || unreachable(cb, new_commit, noid)) return 1; } if (cb->cmd.recno && --(cb->cmd.recno) == 0) return 1; return 0; }
/* * Two-way merge. * * The rule is to "carry forward" what is in the index without losing * information across a "fast-forward", favoring a successful merge * over a merge failure when it makes sense. For details of the * "carry forward" rule, please see <Documentation/git-read-tree.txt>. * */ int twoway_merge(const struct cache_entry * const *src, struct unpack_trees_options *o) { const struct cache_entry *current = src[0]; const struct cache_entry *oldtree = src[1]; const struct cache_entry *newtree = src[2]; if (o->merge_size != 2) return error("Cannot do a twoway merge of %d trees", o->merge_size); if (oldtree == o->df_conflict_entry) oldtree = NULL; if (newtree == o->df_conflict_entry) newtree = NULL; if (current) { if (current->ce_flags & CE_CONFLICTED) { if (same(oldtree, newtree) || o->reset) { if (!newtree) return deleted_entry(current, current, o); else return merged_entry(newtree, current, o); } return reject_merge(current, o); } else if ((!oldtree && !newtree) || /* 4 and 5 */ (!oldtree && newtree && same(current, newtree)) || /* 6 and 7 */ (oldtree && newtree && same(oldtree, newtree)) || /* 14 and 15 */ (oldtree && newtree && !same(oldtree, newtree) && /* 18 and 19 */ same(current, newtree))) { return keep_entry(current, o); } else if (oldtree && !newtree && same(current, oldtree)) { /* 10 or 11 */ return deleted_entry(oldtree, current, o); } else if (oldtree && newtree && same(current, oldtree) && !same(current, newtree)) { /* 20 or 21 */ return merged_entry(newtree, current, o); } else return reject_merge(current, o); } else if (newtree) { if (oldtree && !o->initial_checkout) { /* * deletion of the path was staged; */ if (same(oldtree, newtree)) return 1; return reject_merge(oldtree, o); } return merged_entry(newtree, current, o); } return deleted_entry(oldtree, current, o); }
/* * Bind merge. * * Keep the index entries at stage0, collapse stage1 but make sure * stage0 does not have anything there. */ int bind_merge(const struct cache_entry * const *src, struct unpack_trees_options *o) { const struct cache_entry *old = src[0]; const struct cache_entry *a = src[1]; if (o->merge_size != 1) return error("Cannot do a bind merge of %d trees", o->merge_size); if (a && old) return o->gently ? -1 : error(ERRORMSG(o, ERROR_BIND_OVERLAP), a->name, old->name); if (!a) return keep_entry(old, o); else return merged_entry(a, NULL, o); }
int threeway_merge(const struct cache_entry * const *stages, struct unpack_trees_options *o) { const struct cache_entry *index; const struct cache_entry *head; const struct cache_entry *remote = stages[o->head_idx + 1]; int count; int head_match = 0; int remote_match = 0; int df_conflict_head = 0; int df_conflict_remote = 0; int any_anc_missing = 0; int no_anc_exists = 1; int i; for (i = 1; i < o->head_idx; i++) { if (!stages[i] || stages[i] == o->df_conflict_entry) any_anc_missing = 1; else no_anc_exists = 0; } index = stages[0]; head = stages[o->head_idx]; if (head == o->df_conflict_entry) { df_conflict_head = 1; head = NULL; } if (remote == o->df_conflict_entry) { df_conflict_remote = 1; remote = NULL; } /* * First, if there's a #16 situation, note that to prevent #13 * and #14. */ if (!same(remote, head)) { for (i = 1; i < o->head_idx; i++) { if (same(stages[i], head)) { head_match = i; } if (same(stages[i], remote)) { remote_match = i; } } } /* * We start with cases where the index is allowed to match * something other than the head: #14(ALT) and #2ALT, where it * is permitted to match the result instead. */ /* #14, #14ALT, #2ALT */ if (remote && !df_conflict_head && head_match && !remote_match) { if (index && !same(index, remote) && !same(index, head)) return reject_merge(index, o); return merged_entry(remote, index, o); } /* * If we have an entry in the index cache, then we want to * make sure that it matches head. */ if (index && !same(index, head)) return reject_merge(index, o); if (head) { /* #5ALT, #15 */ if (same(head, remote)) return merged_entry(head, index, o); /* #13, #3ALT */ if (!df_conflict_remote && remote_match && !head_match) return merged_entry(head, index, o); } /* #1 */ if (!head && !remote && any_anc_missing) return 0; /* * Under the "aggressive" rule, we resolve mostly trivial * cases that we historically had git-merge-one-file resolve. */ if (o->aggressive) { int head_deleted = !head; int remote_deleted = !remote; const struct cache_entry *ce = NULL; if (index) ce = index; else if (head) ce = head; else if (remote) ce = remote; else { for (i = 1; i < o->head_idx; i++) { if (stages[i] && stages[i] != o->df_conflict_entry) { ce = stages[i]; break; } } } /* * Deleted in both. * Deleted in one and unchanged in the other. */ if ((head_deleted && remote_deleted) || (head_deleted && remote && remote_match) || (remote_deleted && head && head_match)) { if (index) return deleted_entry(index, index, o); if (ce && !head_deleted) { if (verify_absent(ce, ERROR_WOULD_LOSE_UNTRACKED_REMOVED, o)) return -1; } return 0; } /* * Added in both, identically. */ if (no_anc_exists && head && remote && same(head, remote)) return merged_entry(head, index, o); } /* Below are "no merge" cases, which require that the index be * up-to-date to avoid the files getting overwritten with * conflict resolution files. */ if (index) { if (verify_uptodate(index, o)) return -1; } o->nontrivial_merge = 1; /* #2, #3, #4, #6, #7, #9, #10, #11. */ count = 0; if (!head_match || !remote_match) { for (i = 1; i < o->head_idx; i++) { if (stages[i] && stages[i] != o->df_conflict_entry) { keep_entry(stages[i], o); count++; break; } } } #if DBRT_DEBUG else { fprintf(stderr, "read-tree: warning #16 detected\n"); show_stage_entry(stderr, "head ", stages[head_match]); show_stage_entry(stderr, "remote ", stages[remote_match]); } #endif if (head) { count += keep_entry(head, o); } if (remote) { count += keep_entry(remote, o); } return count; }