def test_pull_state_auto_merges_equal_content(): with TempDir() as d1, TempDir() as d2: # Create R1 with a number of commits # # --- R1 r1 = Repository.init(d1) (d1 / 'hallo.txt').write_text('hallo') r1.commit() r2 = Repository.clone(d2, d1) (d1 / 'hello.txt').write_text('hello') r1.commit() (d1 / 'hallo.txt').write_text('Hallo, Wolt') r1.commit() (d1 / 'hallo.txt').write_text('Hallo, Welt!') (d1 / 'hello.txt').write_text('Hello, World!') r1.commit() # --- R2 # Same content as on R1 (d2 / 'hello.txt').write_text('Hello, World!') r2.commit() conflicts = r2.pull_state(d1) assert len(conflicts) == 0
def test_pull_state_autodetects_rename(): with TempDir() as A, TempDir() as B: rA = Repository.init(A) rB = Repository.clone(B, A) (A / 'x.txt').write_text('Hello, World') rA.commit() conflicts = rB.pull_state(A) assert len(conflicts) == 0 rB.pull_file('x.txt', A) assert (A / 'x.txt').read_bytes() == (B / 'x.txt').read_bytes() (A / 'x.txt').rename(A / 'y.txt') rA.commit() conflicts = rB.pull_state(A) assert len(conflicts) == 0 assert not (A / 'x.txt').exists() assert not (B / 'x.txt').exists() assert (A / 'y.txt').read_bytes() == (B / 'y.txt').read_bytes()
def test_pull_state_automerge_same_content_clock_value(): # White-box test with TempDir() as A, TempDir() as B: rA = Repository.init(A) rB = Repository.clone(B, A) logger.debug('A.id={}'.format(rA.id)) logger.debug('B.id={}'.format(rB.id)) (A / 'hello.txt').write_text('Hello, World!') rA.commit() state_a = rA.repository_state['hello.txt'] (B / 'hello.txt').write_text('Hello, World!') rB.commit() state_b = rB.repository_state['hello.txt'] assert not state_a.clock.comparable( state_b.clock), 'clk A={} clk B={}'.format(state_a.clock, state_b.clock) rB.pull_state(A) # Auto merge should happen and identify the same contents, # resulting in a new commit in B with a merged clock value state_b_new = rB.repository_state['hello.txt'] assert state_b_new.clock > state_b.clock, 'clk Bnew={} clk B={}'.format( state_b_new.clock, state_b.clock) assert state_b_new.clock > state_a.clock, 'clk Bnew={} clk A={}'.format( state_b_new.clock, state_a.clock)
def test_pull_state_finds_conflict(): with TempDir() as d1, TempDir() as d2: r1 = Repository.init(d1) (d1 / 'hallo.txt').write_text('hallo') r1.commit() # clock @R1 { r1 = 1 } r2 = Repository.clone(d2, d1) # clock @R2 { r1 = 1, r2 = 0 } (d1 / 'hallo.txt').write_text('hallo-r1') r1.commit() # clock @R1 { r1 = 2 } # This change (hallo->hallo-r2) is not actually a merge, # but since the file wasnt loaded before in R2, it should have # raised a confirmation to the user. (d2 / 'hallo.txt').write_text('hallo-r2') r2.commit() # clock @R2 { r1 = 2, r2 = 1 } conflicts = r2.pull_state(d1) assert len(conflicts) == 1
def test_clone_copies_certain_files(): with TempDir() as d1, TempDir() as d2: r1 = Repository.init(d1) (d1 / 'hallo.txt').write_text('hallo') r1.commit() r2 = Repository.clone(d2, d1) assert (d2 / d_harmony / 'config').is_file() assert directories_equal(d1 / d_harmony / LOCATION_STATE_DIR, d2 / d_harmony / LOCATION_STATE_DIR)
def test_pull_state_conflicts_on_adding(): with TempDir() as A, TempDir() as B: rA = Repository.init(A) rB = Repository.clone(B, A) (A / 'x.txt').write_text('Added in A') rA.commit() (B / 'x.txt').write_text('Added in B') rB.commit() conflicts = rB.pull_state(A) assert len(conflicts) == 1
def test_rename_updates_location_state(): with TempDir() as A, TempDir() as B, TempDir() as C: rA = Repository.init(A) rB = Repository.clone(B, A) # A (A / 'x.txt').write_text('Hello, World') rA.commit() # B conflicts = rB.pull_state(A) rB.pull_file('x.txt', A) # A (A / 'x.txt').rename(A / 'y.txt') rA.commit() # B conflicts = rB.pull_state(A) change = rB.commit() assert not change # We established in the previous tests already that B # should now have auto-renamed x.txt to y.txt. # After that it shall automatically update its location state # (no additional "commit" necessary after pull_state), # and thus allow the file to be retrieved as y.txt in a third # repository C: # C rC = Repository.clone(C, B) rC.pull_file('y.txt', B) assert (A / 'y.txt').read_bytes() == (C / 'y.txt').read_bytes()
def test_pull_state_finds_conflicts(): with TempDir() as d1, TempDir() as d2: # Create R1 with a number of commits # # -- 1 -- r1 = Repository.init(d1) logger.debug('-- Creating stuff in R1') (d1 / 'hallo.txt').write_text('hallo') r1.commit() logger.debug('-- Cloning') r2 = Repository.clone(d2, d1) # -- 1 -- logger.debug('-- Changing stuff in R1') (d1 / 'hello.txt').write_text('hello') r1.commit() (d1 / 'hallo.txt').write_text('Hallo, Welt') r1.commit() (d1 / 'hallo.txt').write_text('Hallo, Welt!') (d1 / 'hello.txt').write_text('Hello, World!') r1.commit() # -- 2 -- logger.debug('-- Changing stuff in R2') (d2 / 'hallo.txt').write_text('Guten Tag, Welt!') (d2 / 'hello.txt').write_text('Hello, World!!') r2.commit() logger.debug('-- Pull R1 -> R2') conflicts = r2.pull_state(d1) assert len(conflicts) == 2
def test_rename_does_nothing_for_unpulled(): with TempDir() as A, TempDir() as B: rA = Repository.init(A) rB = Repository.clone(B, A) (A / 'x.txt').write_text('Hello, World') rA.commit() conflicts = rB.pull_state(A) assert len(conflicts) == 0 assert not (B / 'x.txt').exists() (A / 'x.txt').rename(A / 'y.txt') rA.commit() conflicts = rB.pull_state(A) assert len(conflicts) == 0 assert not (A / 'x.txt').exists() assert (A / 'y.txt').is_file() assert not (B / 'x.txt').exists() assert not (B / 'y.txt').exists()
def test_clone_empty(): with TempDir() as d1, TempDir() as d2: r1 = Repository.init(d1) r2 = Repository.clone(d2, d1) assert (d2 / d_harmony / 'config').is_file()
def execute(self, ns): r = Repository.clone(working_directory=ns.cwd, location=ns.location)