Dulwich.io dulwich / c91036d
Merge fix from Boris to update directory detection for get_unstaged_changes for Python 3. Fixes #684 Jelmer Vernooń≥ 3 months ago
3 changed file(s) with 86 addition(s) and 17 deletion(s). Raw diff Collapse all Expand all
00 0.19.12 UNRELEASED
1
2 BUG FIXES
3
4 * Update directory detection for `get_unstaged_changes` for Python 3.
5 (Boris Feld, #684)
16
27 0.19.11 2019-02-07
38
603603 return None
604604
605605
606 def _has_directory_changed(tree_path, entry):
607 """Check if a directory has changed after getting an error.
608
609 When handling an error trying to create a blob from a path, call this
610 function. It will check if the path is a directory. If it's a directory
611 and a submodule, check the submodule head to see if it's has changed. If
612 not, consider the file as changed as Git tracked a file and not a
613 directory.
614
615 Return true if the given path should be considered as changed and False
616 otherwise or if the path is not a directory.
617 """
618 # This is actually a directory
619 if os.path.exists(os.path.join(tree_path, b'.git')):
620 # Submodule
621 head = read_submodule_head(tree_path)
622 if entry.sha != head:
623 return True
624 else:
625 # The file was changed to a directory, so consider it removed.
626 return True
627
628 return False
629
630
606631 def get_unstaged_changes(index, root_path, filter_blob_callback=None):
607632 """Walk through an index and check for differences against working tree.
608633
623648
624649 if filter_blob_callback is not None:
625650 blob = filter_blob_callback(blob, tree_path)
626 except OSError as e:
627 if e.errno != errno.ENOENT:
651 except EnvironmentError as e:
652 if e.errno == errno.EISDIR:
653 if _has_directory_changed(tree_path, entry):
654 yield tree_path
655 elif e.errno == errno.ENOENT:
656 # The file was removed, so we assume that counts as
657 # different from whatever file used to exist.
658 yield tree_path
659 else:
628660 raise
629 # The file was removed, so we assume that counts as
630 # different from whatever file used to exist.
631 yield tree_path
632 except IOError as e:
633 if e.errno != errno.EISDIR:
634 raise
635 # This is actually a directory
636 if os.path.exists(os.path.join(tree_path, '.git')):
637 # Submodule
638 head = read_submodule_head(tree_path)
639 if entry.sha != head:
640 yield tree_path
641 else:
642 # The file was changed to a directory, so consider it removed.
643 yield tree_path
644661 else:
645662 if blob.id != entry.sha:
646663 yield tree_path
670670
671671 self.assertEqual(list(changes), [b'foo1'])
672672
673 def test_get_unstaged_changes_removed_replaced_by_directory(self):
674 """Unit test for get_unstaged_changes."""
675
676 repo_dir = tempfile.mkdtemp()
677 self.addCleanup(shutil.rmtree, repo_dir)
678 with Repo.init(repo_dir) as repo:
679
680 # Commit a dummy file then modify it
681 foo1_fullpath = os.path.join(repo_dir, 'foo1')
682 with open(foo1_fullpath, 'wb') as f:
683 f.write(b'origstuff')
684
685 repo.stage(['foo1'])
686 repo.do_commit(b'test status', author=b'author <email>',
687 committer=b'committer <email>')
688
689 os.remove(foo1_fullpath)
690 os.mkdir(foo1_fullpath)
691
692 changes = get_unstaged_changes(repo.open_index(), repo_dir)
693
694 self.assertEqual(list(changes), [b'foo1'])
695
696 @skipIf(not can_symlink(), 'Requires symlink support')
697 def test_get_unstaged_changes_removed_replaced_by_link(self):
698 """Unit test for get_unstaged_changes."""
699
700 repo_dir = tempfile.mkdtemp()
701 self.addCleanup(shutil.rmtree, repo_dir)
702 with Repo.init(repo_dir) as repo:
703
704 # Commit a dummy file then modify it
705 foo1_fullpath = os.path.join(repo_dir, 'foo1')
706 with open(foo1_fullpath, 'wb') as f:
707 f.write(b'origstuff')
708
709 repo.stage(['foo1'])
710 repo.do_commit(b'test status', author=b'author <email>',
711 committer=b'committer <email>')
712
713 os.remove(foo1_fullpath)
714 os.symlink(os.path.dirname(foo1_fullpath), foo1_fullpath)
715
716 changes = get_unstaged_changes(repo.open_index(), repo_dir)
717
718 self.assertEqual(list(changes), [b'foo1'])
719
673720
674721 class TestValidatePathElement(TestCase):
675722