import io
p='.github/ci/classify-changes-selftest.py'
s=io.open(p,encoding='utf-8',newline='').read(); nl='\r\n' if '\r\n' in s else '\n'
def rep(old,new):
    global s
    old=old.replace('\n',nl); new=new.replace('\n',nl)
    assert s.count(old)==1,(s.count(old),old[:60]); s=s.replace(old,new)
rep('''    def __init__(self, diffs=None, reachable_after=0, ancestor=True, raise_on=None):
        self.diffs = diffs or {}
        self.reachable_after = reachable_after  # cat-file succeeds on the Nth probe (0 = never)
        self.ancestor = ancestor
        self.raise_on = raise_on
        self.calls = []
        self.probes = 0''','''    def __init__(self, diffs=None, reachable_after=0, ancestor=True, raise_on=None,
                 ancestor_after_fetches=0, shallow=True):
        self.diffs = diffs or {}
        self.reachable_after = reachable_after  # cat-file succeeds on the Nth probe (0 = never)
        self.ancestor = ancestor
        # is-ancestor answers False until this many deepen fetches have run: the
        # stale-object shallow graft, where the OBJECT is present but the
        # graph from sha does not reach it yet (measured on kitsubito, IR-147).
        self.ancestor_after_fetches = ancestor_after_fetches
        self.shallow = shallow
        self.raise_on = raise_on
        self.calls = []
        self.probes = 0
        self.fetches = 0'''),
rep('''        if args[0] == "merge-base":
            return (0 if self.ancestor else 1), ""
        if args[0] == "fetch":
            return 0, ""''','''        if args[0] == "merge-base":
            linked = self.fetches >= self.ancestor_after_fetches
            return (0 if (self.ancestor and linked) else 1), ""
        if args[0] == "fetch":
            self.fetches += 1
            return 0, ""
        if args[0] == "rev-parse":
            return 0, ("true" if self.shallow else "false") + "\n"'''),
rep('''    def test_before_not_ancestor_runs_units(self):
        g = FakeGit({(BEFORE, SHA): ["a.md"]}, reachable_after=1, ancestor=False)
        self.assertEqual(push(g)[0], "CLASSIFY code=true reason=before-not-ancestor")''','''    def test_before_not_ancestor_on_a_complete_graph_runs_units(self):
        g = FakeGit({(BEFORE, SHA): ["a.md"]}, reachable_after=1, ancestor=False, shallow=False)
        self.assertEqual(push(g)[0], "CLASSIFY code=true reason=before-not-ancestor")

    def test_present_object_on_a_shallow_graft_still_deepens(self):
        # IR-147 field defect (main run 35998753683): a STALE before object is
        # present, so a presence probe passes at step 0, but the depth-2 graph
        # from sha is grafted short of it and is-ancestor says no. Presence
        # must not stop the deepening; connectivity must.
        g = FakeGit({(BEFORE, SHA): ["docs/a.md"]}, reachable_after=1, ancestor_after_fetches=1)
        self.assertEqual(push(g)[0], "CLASSIFY code=false reason=docs-only")
        self.assertEqual([c[2] for c in g.calls if c[0] == "fetch"], ["--deepen=50"])

    def test_a_shallow_graph_that_never_decides_is_undecidable_not_non_ancestor(self):
        g = FakeGit({(BEFORE, SHA): ["docs/a.md"]}, reachable_after=1, ancestor=False, shallow=True)
        self.assertEqual(push(g)[0], "CLASSIFY code=true reason=before-undecidable")
        self.assertEqual([c[2] for c in g.calls if c[0] == "fetch"], ["--deepen=50", "--deepen=500"])'''),
io.open(p,'w',encoding='utf-8',newline='').write(s)
print('ok')
