652
649
self.assertIsInstance(state, dirstate.DirState)
653
650
lines = state.get_lines()
651
self.assertFileEqual(''.join(state.get_lines()),
653
self.check_state_with_reopen(expected_result, state)
656
# On win32 you can't read from a locked file, even within the same
657
# process. So we have to unlock and release before we check the file
659
self.assertFileEqual(''.join(lines), 'dirstate')
660
state.lock_read() # check_state_with_reopen will unlock
661
self.check_state_with_reopen(expected_result, state)
664
659
class TestDirStateManipulations(TestCaseWithDirState):
691
686
# This will unlock it
692
687
self.check_state_with_reopen(expected_result, state)
694
def test_set_state_from_inventory_mixed_paths(self):
695
tree1 = self.make_branch_and_tree('tree1')
696
self.build_tree(['tree1/a/', 'tree1/a/b/', 'tree1/a-b/',
697
'tree1/a/b/foo', 'tree1/a-b/bar'])
700
tree1.add(['a', 'a/b', 'a-b', 'a/b/foo', 'a-b/bar'],
701
['a-id', 'b-id', 'a-b-id', 'foo-id', 'bar-id'])
702
tree1.commit('rev1', rev_id='rev1')
703
root_id = tree1.get_root_id()
704
inv = tree1.inventory
707
expected_result1 = [('', '', root_id, 'd'),
708
('', 'a', 'a-id', 'd'),
709
('', 'a-b', 'a-b-id', 'd'),
710
('a', 'b', 'b-id', 'd'),
711
('a/b', 'foo', 'foo-id', 'f'),
712
('a-b', 'bar', 'bar-id', 'f'),
714
expected_result2 = [('', '', root_id, 'd'),
715
('', 'a', 'a-id', 'd'),
716
('', 'a-b', 'a-b-id', 'd'),
717
('a-b', 'bar', 'bar-id', 'f'),
719
state = dirstate.DirState.initialize('dirstate')
721
state.set_state_from_inventory(inv)
723
for entry in state._iter_entries():
724
values.append(entry[0] + entry[1][0][:1])
725
self.assertEqual(expected_result1, values)
727
state.set_state_from_inventory(inv)
729
for entry in state._iter_entries():
730
values.append(entry[0] + entry[1][0][:1])
731
self.assertEqual(expected_result2, values)
735
689
def test_set_path_id_no_parents(self):
736
690
"""The id of a path can be changed trivally with no parents."""
737
691
state = dirstate.DirState.initialize('dirstate')
1492
1446
self.assertEqual(dirstate.DirState.IN_MEMORY_MODIFIED,
1493
1447
state._dirblock_state)
1494
self.assertEqual([('f', '', 14, False, dirstate.DirState.NULLSTAT)],
1498
1450
# However, if we move the clock forward so the file is considered
1499
# "stable", it should just cache the value.
1500
state.adjust_time(+20)
1451
# "stable", it should just returned the cached value.
1452
state.adjust_time(20)
1501
1453
link_or_sha1 = state.update_entry(entry, abspath='a',
1502
1454
stat_value=stat_value)
1503
1455
self.assertEqual('b50e5406bb5e153ebbeb20268fcf37c87e1ecfb6',
1505
1457
self.assertEqual([('sha1', 'a'), ('is_exec', mode, False),
1506
1458
('sha1', 'a'), ('is_exec', mode, False),
1507
('sha1', 'a'), ('is_exec', mode, False),
1509
self.assertEqual([('f', link_or_sha1, 14, False, packed_stat)],
1512
# Subsequent calls will just return the cached value
1513
link_or_sha1 = state.update_entry(entry, abspath='a',
1514
stat_value=stat_value)
1461
def test_update_entry_no_stat_value(self):
1462
"""Passing the stat_value is optional."""
1463
state, entry = self.get_state_with_a()
1464
state.adjust_time(-10) # Make sure the file looks new
1465
self.build_tree(['a'])
1466
# Add one where we don't provide the stat or sha already
1467
link_or_sha1 = state.update_entry(entry, abspath='a')
1515
1468
self.assertEqual('b50e5406bb5e153ebbeb20268fcf37c87e1ecfb6',
1517
self.assertEqual([('sha1', 'a'), ('is_exec', mode, False),
1518
('sha1', 'a'), ('is_exec', mode, False),
1519
('sha1', 'a'), ('is_exec', mode, False),
1470
stat_value = os.lstat('a')
1471
self.assertEqual([('lstat', 'a'), ('sha1', 'a'),
1472
('is_exec', stat_value.st_mode, False),
1521
self.assertEqual([('f', link_or_sha1, 14, False, packed_stat)],
1524
1475
def test_update_entry_symlink(self):
1525
1476
"""Update entry should read symlinks."""
1539
1490
stat_value=stat_value)
1540
1491
self.assertEqual('target', link_or_sha1)
1541
1492
self.assertEqual([('read_link', 'a', '')], state._log)
1542
# Dirblock is not updated (the link is too new)
1543
self.assertEqual([('l', '', 6, False, dirstate.DirState.NULLSTAT)],
1493
# Dirblock is updated
1494
self.assertEqual([('l', link_or_sha1, 6, False, packed_stat)],
1545
1496
self.assertEqual(dirstate.DirState.IN_MEMORY_MODIFIED,
1546
1497
state._dirblock_state)
1550
1501
stat_value=stat_value)
1551
1502
self.assertEqual('target', link_or_sha1)
1552
1503
self.assertEqual([('read_link', 'a', ''),
1553
('read_link', 'a', ''),
1504
('read_link', 'a', 'target'),
1555
self.assertEqual([('l', '', 6, False, dirstate.DirState.NULLSTAT)],
1557
1506
state.adjust_time(+20) # Skip into the future, all files look old
1558
1507
link_or_sha1 = state.update_entry(entry, abspath='a',
1559
1508
stat_value=stat_value)
1560
1509
self.assertEqual('target', link_or_sha1)
1561
# We need to re-read the link because only now can we cache it
1562
self.assertEqual([('read_link', 'a', ''),
1563
('read_link', 'a', ''),
1564
('read_link', 'a', ''),
1566
self.assertEqual([('l', 'target', 6, False, packed_stat)],
1569
# Another call won't re-read the link
1570
self.assertEqual([('read_link', 'a', ''),
1571
('read_link', 'a', ''),
1572
('read_link', 'a', ''),
1574
link_or_sha1 = state.update_entry(entry, abspath='a',
1575
stat_value=stat_value)
1576
self.assertEqual('target', link_or_sha1)
1577
self.assertEqual([('l', 'target', 6, False, packed_stat)],
1580
def do_update_entry(self, state, entry, abspath):
1581
stat_value = os.lstat(abspath)
1582
return state.update_entry(entry, abspath, stat_value)
1510
# There should not be a new read_link call.
1511
# (this is a weak assertion, because read_link is fairly inexpensive,
1512
# versus the number of symlinks that we would have)
1513
self.assertEqual([('read_link', 'a', ''),
1514
('read_link', 'a', 'target'),
1584
1517
def test_update_entry_dir(self):
1585
1518
state, entry = self.get_state_with_a()
1586
1519
self.build_tree(['a/'])
1587
self.assertIs(None, self.do_update_entry(state, entry, 'a'))
1589
def test_update_entry_dir_unchanged(self):
1590
state, entry = self.get_state_with_a()
1591
self.build_tree(['a/'])
1592
state.adjust_time(+20)
1593
self.assertIs(None, self.do_update_entry(state, entry, 'a'))
1594
self.assertEqual(dirstate.DirState.IN_MEMORY_MODIFIED,
1595
state._dirblock_state)
1597
self.assertEqual(dirstate.DirState.IN_MEMORY_UNMODIFIED,
1598
state._dirblock_state)
1599
self.assertIs(None, self.do_update_entry(state, entry, 'a'))
1600
self.assertEqual(dirstate.DirState.IN_MEMORY_UNMODIFIED,
1601
state._dirblock_state)
1603
def test_update_entry_file_unchanged(self):
1604
state, entry = self.get_state_with_a()
1605
self.build_tree(['a'])
1606
sha1sum = 'b50e5406bb5e153ebbeb20268fcf37c87e1ecfb6'
1607
state.adjust_time(+20)
1608
self.assertEqual(sha1sum, self.do_update_entry(state, entry, 'a'))
1609
self.assertEqual(dirstate.DirState.IN_MEMORY_MODIFIED,
1610
state._dirblock_state)
1612
self.assertEqual(dirstate.DirState.IN_MEMORY_UNMODIFIED,
1613
state._dirblock_state)
1614
self.assertEqual(sha1sum, self.do_update_entry(state, entry, 'a'))
1615
self.assertEqual(dirstate.DirState.IN_MEMORY_UNMODIFIED,
1616
state._dirblock_state)
1520
self.assertIs(None, state.update_entry(entry, 'a'))
1618
1522
def create_and_test_file(self, state, entry):
1619
1523
"""Create a file at 'a' and verify the state finds it.
1663
1567
stat_value = os.lstat('a')
1664
1568
packed_stat = dirstate.pack_stat(stat_value)
1666
link_or_sha1 = self.do_update_entry(state, entry, abspath='a')
1570
link_or_sha1 = state.update_entry(entry, abspath='a')
1667
1571
self.assertEqual('path/to/foo', link_or_sha1)
1668
1572
self.assertEqual([('l', 'path/to/foo', 11, False, packed_stat)],
1670
1574
return packed_stat
1576
def test_update_missing_file(self):
1577
state, entry = self.get_state_with_a()
1578
packed_stat = self.create_and_test_file(state, entry)
1579
# Now if we delete the file, update_entry should recover and
1582
self.assertIs(None, state.update_entry(entry, abspath='a'))
1583
# And the record shouldn't be changed.
1584
digest = 'b50e5406bb5e153ebbeb20268fcf37c87e1ecfb6'
1585
self.assertEqual([('f', digest, 14, False, packed_stat)],
1588
def test_update_missing_dir(self):
1589
state, entry = self.get_state_with_a()
1590
packed_stat = self.create_and_test_dir(state, entry)
1591
# Now if we delete the directory, update_entry should recover and
1594
self.assertIs(None, state.update_entry(entry, abspath='a'))
1595
self.assertEqual([('d', '', 0, False, packed_stat)], entry[1])
1597
def test_update_missing_symlink(self):
1598
if not osutils.has_symlinks():
1599
# PlatformDeficiency / TestSkipped
1600
raise TestSkipped("No symlink support")
1601
state, entry = self.get_state_with_a()
1602
packed_stat = self.create_and_test_symlink(state, entry)
1604
self.assertIs(None, state.update_entry(entry, abspath='a'))
1605
# And the record shouldn't be changed.
1606
self.assertEqual([('l', 'path/to/foo', 11, False, packed_stat)],
1672
1609
def test_update_file_to_dir(self):
1673
1610
"""If a file changes to a directory we return None for the sha.
1674
1611
We also update the inventory record.
1676
1613
state, entry = self.get_state_with_a()
1677
# The file sha1 won't be cached unless the file is old
1678
state.adjust_time(+10)
1679
1614
self.create_and_test_file(state, entry)
1681
1616
self.create_and_test_dir(state, entry)
1750
1675
packed_stat = dirstate.pack_stat(stat_value)
1752
1677
state.adjust_time(-10) # Make sure everything is new
1678
# Make sure it wants to kkkkkkkk
1753
1679
state.update_entry(entry, abspath='a', stat_value=stat_value)
1755
1681
# The row is updated, but the executable bit stays set.
1756
self.assertEqual([('f', '', 14, True, dirstate.DirState.NULLSTAT)],
1759
# Make the disk object look old enough to cache
1760
state.adjust_time(+20)
1761
1682
digest = 'b50e5406bb5e153ebbeb20268fcf37c87e1ecfb6'
1762
state.update_entry(entry, abspath='a', stat_value=stat_value)
1763
1683
self.assertEqual([('f', digest, 14, True, packed_stat)], entry[1])