|
29 | 29 | hex_to_bin
|
30 | 30 | )
|
31 | 31 |
|
| 32 | +from config import ( |
| 33 | + GitConfigParser, |
| 34 | + SectionConstraint |
| 35 | + ) |
| 36 | + |
32 | 37 | from exc import GitCommandError
|
33 | 38 |
|
34 | 39 | __all__ = ("SymbolicReference", "Reference", "HEAD", "Head", "TagReference",
|
@@ -701,6 +706,8 @@ class Head(Reference):
|
701 | 706 | >>> head.commit.hexsha
|
702 | 707 | '1c09f116cbc2cb4100fb6935bb162daa4723f455'"""
|
703 | 708 | _common_path_default = "refs/heads"
|
| 709 | + k_config_remote = "remote" |
| 710 | + k_config_remote_ref = "merge" # branch to merge from remote |
704 | 711 |
|
705 | 712 | @classmethod
|
706 | 713 | def create(cls, repo, path, commit='HEAD', force=False, **kwargs):
|
@@ -747,6 +754,44 @@ def delete(cls, repo, *heads, **kwargs):
|
747 | 754 | flag = "-D"
|
748 | 755 | repo.git.branch(flag, *heads)
|
749 | 756 |
|
| 757 | + |
| 758 | + def set_tracking_branch(self, remote_reference): |
| 759 | + """Configure this branch to track the given remote reference. This will alter |
| 760 | + this branch's configuration accordingly. |
| 761 | + :param remote_reference: The remote reference to track or None to untrack |
| 762 | + any references |
| 763 | + :return: self""" |
| 764 | + if remote_reference is not None and not isinstance(remote_reference, RemoteReference): |
| 765 | + raise ValueError("Incorrect parameter type: %r" % remote_reference) |
| 766 | + # END handle type |
| 767 | + |
| 768 | + writer = self.config_writer() |
| 769 | + if remote_reference is None: |
| 770 | + writer.remove_option(self.k_config_remote) |
| 771 | + writer.remove_option(self.k_config_remote_ref) |
| 772 | + if len(writer.options()) == 0: |
| 773 | + writer.remove_section() |
| 774 | + # END handle remove section |
| 775 | + else: |
| 776 | + writer.set_value(self.k_config_remote, remote_reference.remote_name) |
| 777 | + writer.set_value(self.k_config_remote_ref, Head.to_full_path(remote_reference.remote_head)) |
| 778 | + # END handle ref value |
| 779 | + |
| 780 | + return self |
| 781 | + |
| 782 | + |
| 783 | + def tracking_branch(self): |
| 784 | + """:return: The remote_reference we are tracking, or None if we are |
| 785 | + not a tracking branch""" |
| 786 | + reader = self.config_reader() |
| 787 | + if reader.has_option(self.k_config_remote) and reader.has_option(self.k_config_remote_ref): |
| 788 | + ref = Head(self.repo, Head.to_full_path(reader.get_value(self.k_config_remote_ref))) |
| 789 | + remote_refpath = RemoteReference.to_full_path(join_path(reader.get_value(self.k_config_remote), ref.name)) |
| 790 | + return RemoteReference(self.repo, remote_refpath) |
| 791 | + # END handle have tracking branch |
| 792 | + |
| 793 | + # we are not a tracking branch |
| 794 | + return None |
750 | 795 |
|
751 | 796 | def rename(self, new_path, force=False):
|
752 | 797 | """Rename self to a new path
|
@@ -800,6 +845,29 @@ def checkout(self, force=False, **kwargs):
|
800 | 845 | self.repo.git.checkout(self, **kwargs)
|
801 | 846 | return self.repo.active_branch
|
802 | 847 |
|
| 848 | + #{ Configruation |
| 849 | + |
| 850 | + def _config_parser(self, read_only): |
| 851 | + if read_only: |
| 852 | + parser = self.repo.config_reader() |
| 853 | + else: |
| 854 | + parser = self.repo.config_writer() |
| 855 | + # END handle parser instance |
| 856 | + |
| 857 | + return SectionConstraint(parser, 'branch "%s"' % self.name) |
| 858 | + |
| 859 | + def config_reader(self): |
| 860 | + """:return: A configuration parser instance constrained to only read |
| 861 | + this instance's values""" |
| 862 | + return self._config_parser(read_only=True) |
| 863 | + |
| 864 | + def config_writer(self): |
| 865 | + """:return: A configuration writer instance with read-and write acccess |
| 866 | + to options of this head""" |
| 867 | + return self._config_parser(read_only=False) |
| 868 | + |
| 869 | + #} END configuration |
| 870 | + |
803 | 871 |
|
804 | 872 | class TagReference(Reference):
|
805 | 873 | """Class representing a lightweight tag reference which either points to a commit
|
@@ -893,6 +961,16 @@ class RemoteReference(Head):
|
893 | 961 | """Represents a reference pointing to a remote head."""
|
894 | 962 | _common_path_default = "refs/remotes"
|
895 | 963 |
|
| 964 | + |
| 965 | + @classmethod |
| 966 | + def iter_items(cls, repo, common_path = None, remote=None): |
| 967 | + """Iterate remote references, and if given, constrain them to the given remote""" |
| 968 | + common_path = common_path or cls._common_path_default |
| 969 | + if remote is not None: |
| 970 | + common_path = join_path(common_path, str(remote)) |
| 971 | + # END handle remote constraint |
| 972 | + return super(RemoteReference, cls).iter_items(repo, common_path) |
| 973 | + |
896 | 974 | @property
|
897 | 975 | def remote_name(self):
|
898 | 976 | """
|
|
0 commit comments