def test_divergence_resolver(issue_1, issue_2, issue_3, monkeypatch): resolved_issues = [issue_1, issue_2, issue_3] resolved_tracker = Tracker() summary_edit = "This edit resolves the create-edit-divergence" monkeypatch.setattr("builtins.input", lambda x: summary_edit) for issue in resolved_issues: resolved_tracker.track_or_update_uuid(issue.uuid, issue.id) issue_3_json = JsonConvert.ToJSON(issue_3) issue_3_copy = JsonConvert.FromJSON(issue_3_json) issue_3_copy.summary = "This is the edited field for the create-edit-divergence" issue_3_copy.id = issue_2.id expected = JsonConvert.FromJSON(issue_3_json) expected.summary = summary_edit resolver = DivergenceConflictResolver() resolver.resolved_tracker = resolved_tracker resolver.resolved_conflicts = resolved_issues resolver.diverged_issues = [(issue_3, issue_3_copy)] resolution = resolver.generate_resolution() assert [issue_3, expected] == resolution.resolved_issues
def test_create_resolution(issue_1: Issue, issue_2: Issue, monkeypatch, first_repo: git.Repo): handler = IssueHandler() issue_1_path = handler.get_issue_path(issue_1) issue_2_path = handler.get_issue_path(issue_2) issues = [issue_1, issue_2] os.chdir(first_repo.working_dir) monkeypatch.setattr("git_issue.git_manager.GitManager.get_choice_from_user", lambda x, y: True) monkeypatch.setattr("builtins.input", lambda x: 'Y') uuids = [UUIDTrack(issue_1.uuid, issue_1.id), UUIDTrack(issue_2.uuid, issue_2.id)] resolution = CreateResolutionTool(issues, Tracker(len(uuids), uuids)) resolution.resolve() GitManager().commit("-m", "merge conflict resolution") assert issue_1_path.exists() assert issue_2_path.exists() result_1 = handler.get_issue_from_issue_id(issues[0].id) result_2 = handler.get_issue_from_issue_id(issues[1].id) assert issues[0] == result_1 assert issues[1] == result_2
def test_produce_divergence_resolver(issue_1, issue_2, issue_3, first_repo): resolved_issues = [issue_1, issue_2, issue_3] resolved_tracker = Tracker() for issue in resolved_issues: resolved_tracker.track_or_update_uuid(issue.uuid, issue.id) issue_2_json = JsonConvert.ToJSON(issue_2) issue_2_copy = JsonConvert.FromJSON(issue_2_json) issue_2_copy.uuid = 53368803138698180295652887974160049016 conflict = ConflictInfo(IssueHandler().get_issue_path(issue_2), [issue_2, issue_2, issue_2_copy]) merger = GitMerge(first_repo) resolver = merger.produce_create_edit_divergence_resolver([conflict], resolved_issues, resolved_tracker) assert resolved_issues == resolver.resolved_conflicts and resolved_tracker == resolver.resolved_tracker assert [(issue_2, issue_2_copy)] == resolver.diverged_issues
def test_produce_create_resolver(issue_1: Issue, issue_2: Issue, first_repo): conflict = ConflictInfo("fake_path", [issue_1, issue_2]) # Not what we're testing in this unit, but it's imperative that we know # what we're dealing with is a create conflict assert conflict.type == ConflictType.CREATE merger = GitMerge(first_repo) tracks = [UUIDTrack(issue.uuid, issue.id) for issue in conflict.conflicts] result = merger.produce_create_resolver([conflict, ConflictInfo("Another fake path", [Tracker(len(tracks), tracks)])]) assert 1 == len(result.conflicts) and 2 == len(result.conflicts[0].conflicts) assert 2 == len(result.tracker.tracked_uuids) and 2 == result.tracker.issue_count assert conflict == result.conflicts[0] assert tracks == result.tracker.tracked_uuids
def produce_create_resolver(self, conflicts: [ConflictInfo ] = None) -> ConflictResolver: resolver = CreateConflictResolver() resolver.conflicts = self._get_conflicts_of_type( ConflictType.CREATE, conflicts) trackers = self._get_conflicts_of_type(ConflictType.TRACKER, conflicts) # uuids = [] tracking = [] for conflict in trackers: for tracker in conflict.conflicts: for track in tracker.tracked_uuids: if track not in tracking: tracking.append(track) # for info in resolver.conflicts: # uuids = [UUIDTrack(issue.uuid, issue.id) for issue in info.conflicts] resolver.tracker = Tracker(len(tracking), tracking) return resolver
def merge(self, merger): print("Beginning merge process") conflicts = merger.parse_unmerged_conflicts() create_resolver = merger.produce_create_resolver(conflicts) create_resolution = create_resolver.generate_resolution() create_resolution.resolve() tracker = create_resolution.tracker if create_resolution.tracker.issue_count != 0 else Tracker.obtain_tracker( ) divergence_resolver = merger.produce_create_edit_divergence_resolver( conflicts, create_resolution.resolved_issues, tracker) divergence_resolution = divergence_resolver.generate_resolution() divergence_resolution.resolve() comment_resolvers = merger.produce_comment_index_resolvers(conflicts) for resolver in comment_resolvers: resolution = resolver.generate_resolution() resolution.resolve() manual_conflicts = merger.filter_manual_conflicts(conflicts) if manual_conflicts == []: self.repo.git.commit("-m", "merge conflict resolution") print("Merge successful. All files have been merged.") else: print( "I wasn't able to resolve all the conflicts. This typically happens when something's been edited " "in both the remote and current repository.") print("Here are the files I couldn't resolve:") for conflict in manual_conflicts: print(f"\t{conflict.path}") gm = GitManager() if gm.is_worktree(): print( "Exiting program to prevent branch unloading. This would cause loss of resolved conflicts." ) exit()
def __init__(self, tracker=None): self.tracker = tracker if tracker is not None else Tracker.obtain_tracker( )
def generate_issue_id(): tracker = Tracker.obtain_tracker() return "{}-{}".format(tracker.ISSUE_IDENTIFIER, (tracker.issue_count + 1))
def generate_resolution(self): """ Resolves conflicts by re-ordering the issues based on their creation date. The conflicts are resolved by giving the oldest issue the first conflicting issue ID. Returns a tuple containing the list of resolved conflicts, and an updated tracker. These resolved conflicts are NOT stored to fie by this method. This is left as a job for the consumer. """ # Create copies of data to avoid mutating them as a side affect conflicts = [] for info in self.conflicts: for issue in info.conflicts: conflicts.append(issue) if self.tracker is None: tracker = Tracker.obtain_tracker() else: tracker = Tracker(self.tracker.issue_count, self.tracker.tracked_uuids.copy()) complete = False handler = IssueHandler(tracker) ids = [issue.id for issue in conflicts] while not complete: to_add = [] for issue in conflicts: next_id = handler.next_issue_id(issue.id) while next_id in ids: next_id = handler.next_issue_id(next_id) if next_id not in ids: if handler.does_issue_exist(next_id): missing = handler.get_issue_from_issue_id(next_id) to_add.append(missing) ids.append(next_id) for issue in to_add: conflicts.append(issue) ids.append(issue.id) complete = len(to_add) == 0 conflicts.sort(key=lambda x: x.date) sorted_ids = list(set(ids)) sorted_ids.sort() assert len(sorted_ids) >= len(conflicts) index = 0 for issue in conflicts: new_id = sorted_ids[index] issue.id = new_id tracker.track_or_update_uuid(issue.uuid, new_id) index += 1 return CreateResolutionTool(conflicts, tracker)