76
81
return self._lookup_revno(self.new_revid)
79
class LocalGitTagDict(tag.BasicTags):
80
"""Dictionary with tags in a local repository."""
84
class GitTags(tag.BasicTags):
85
"""Ref-based tag dictionary."""
82
87
def __init__(self, branch):
83
88
self.branch = branch
84
89
self.repository = branch.repository
91
def _iter_tag_refs(self, refs):
92
raise NotImplementedError(self._iter_tag_refs)
94
def _merge_to_git(self, to_tags, refs, overwrite=False):
95
target_repo = to_tags.repository
97
for k, v in refs.iteritems():
100
if overwrite or not k in self.target.repository.refs:
101
target_repo.refs[k] = v
102
elif target_repo.repository.refs[k] == v:
105
conflicts.append((ref_to_tag_name(k), v, target_repo.refs[k]))
108
def _merge_to_non_git(self, to_tags, refs, overwrite=False):
109
unpeeled_map = defaultdict(set)
111
result = dict(to_tags.get_tag_dict())
112
for n, peeled, unpeeled, bzr_revid in self._iter_tag_refs(refs):
113
if unpeeled is not None:
114
unpeeled_map[peeled].add(unpeeled)
115
if n not in result or overwrite:
116
result[n] = bzr_revid
117
elif result[n] == bzr_revid:
120
conflicts.append((n, result[n], bzr_revid))
121
to_tags._set_tag_dict(result)
122
if len(unpeeled_map) > 0:
123
map_file = UnpeelMap.from_repository(to_tags.branch.repository)
124
map_file.update(unpeeled_map)
125
map_file.save_in_repository(to_tags.branch.repository)
128
def merge_to(self, to_tags, overwrite=False, ignore_master=False,
130
if source_refs is None:
131
source_refs = self.repository.get_refs()
134
if isinstance(to_tags, GitTags):
135
return self._merge_to_git(to_tags, source_refs,
141
master = to_tags.branch.get_master_branch()
142
conflicts = self._merge_to_non_git(to_tags, source_refs,
144
if master is not None:
145
conflicts += self.merge_to(to_tags, overwrite=overwrite,
146
source_refs=source_refs,
147
ignore_master=ignore_master)
86
150
def get_tag_dict(self):
88
for k,v in extract_tags(self.repository._git.get_refs()).iteritems():
152
refs = self.repository.get_refs()
153
for (name, peeled, unpeeled, bzr_revid) in self._iter_tag_refs(refs):
154
ret[name] = bzr_revid
158
class LocalGitTagDict(GitTags):
159
"""Dictionary with tags in a local repository."""
161
def __init__(self, branch):
162
super(LocalGitTagDict, self).__init__(branch)
163
self.refs = self.repository._git.refs
165
def _iter_tag_refs(self, refs):
166
"""Iterate over the tag refs.
168
:param refs: Refs dictionary (name -> git sha1)
169
:return: iterator over (name, peeled_sha1, unpeeled_sha1, bzr_revid)
171
for k, (peeled, unpeeled) in extract_tags(refs).iteritems():
90
obj = self.repository._git[v]
173
obj = self.repository._git[peeled]
92
mutter("Tag %s points at unknown object %s, ignoring", v, obj)
175
mutter("Tag %s points at unknown object %s, ignoring", peeled,
178
# FIXME: this shouldn't really be necessary, the repository
179
# already should have these unpeeled.
94
180
while isinstance(obj, Tag):
96
obj = self.repository._git[v]
181
peeled = obj.object[1]
182
obj = self.repository._git[peeled]
97
183
if not isinstance(obj, Commit):
98
184
mutter("Tag %s points at object %r that is not a commit, "
99
185
"ignoring", k, obj)
101
ret[k] = self.branch.lookup_foreign_revision_id(v)
187
yield (k, peeled, unpeeled,
188
self.branch.lookup_foreign_revision_id(peeled))
104
191
def _set_tag_dict(self, to_dict):
105
192
extra = set(self.repository._git.get_refs().keys())
604
698
result.old_revid = self.target.last_revision()
605
699
refs, stop_revision = self.update_refs(stop_revision)
606
700
self.target.generate_revision_history(stop_revision, result.old_revid)
607
self.update_tags(refs)
701
result.tag_conflicts = self.source.tags.merge_to(self.target.tags,
702
source_refs=refs, overwrite=overwrite)
608
703
result.new_revid = self.target.last_revision()
611
def update_tags(self, refs):
612
for name, v in extract_tags(refs).iteritems():
613
revid = self.target.lookup_foreign_revision_id(v)
614
self.target.tags.set_tag(name, revid)
616
706
def update_refs(self, stop_revision=None):
617
707
interrepo = repository.InterRepository.get(self.source.repository,
618
708
self.target.repository)
662
753
def _get_new_refs(self, stop_revision=None):
663
754
if stop_revision is None:
664
stop_revision = self.source.last_revision()
755
(stop_revno, stop_revision) = self.source.last_revision_info()
665
756
assert type(stop_revision) is str
666
757
main_ref = self.target.ref or "refs/heads/master"
667
758
refs = { main_ref: (None, stop_revision) }
668
759
for name, revid in self.source.tags.get_tag_dict().iteritems():
669
760
if self.source.repository.has_revision(revid):
670
761
refs[tag_name_to_ref(name)] = (None, revid)
671
return refs, main_ref
762
return refs, main_ref, (stop_revno, stop_revision)
673
764
def pull(self, overwrite=False, stop_revision=None, local=False,
674
765
possible_transports=None):
676
767
result = GitBranchPullResult()
677
768
result.source_branch = self.source
678
769
result.target_branch = self.target
679
new_refs, main_ref = self._get_new_refs(stop_revision)
770
new_refs, main_ref, stop_revinfo = self._get_new_refs(stop_revision)
680
771
def update_refs(old_refs):
681
772
refs = dict(old_refs)
682
773
# FIXME: Check for diverged branches
683
774
refs.update(new_refs)
685
776
old_refs, new_refs = self.interrepo.fetch_refs(update_refs)
686
result.old_revid = self.target.lookup_foreign_revision_id(
687
old_refs.get(main_ref, ZERO_SHA))
688
result.new_revid = new_refs[main_ref]
777
(result.old_revid, old_sha1) = old_refs.get(main_ref, (ZERO_SHA, NULL_REVISION))
778
if result.old_revid is None:
779
result.old_revid = self.target.lookup_foreign_revision_id(old_sha1)
780
result.new_revid = new_refs[main_ref][1]
691
783
def push(self, overwrite=False, stop_revision=None,
704
796
(result.old_revid, old_sha1) = old_refs.get(main_ref, (ZERO_SHA, NULL_REVISION))
705
797
if result.old_revid is None:
706
798
result.old_revid = self.target.lookup_foreign_revision_id(old_sha1)
707
result.new_revid = new_refs[main_ref]
799
result.new_revid = new_refs[main_ref][1]
710
802
def lossy_push(self, stop_revision=None):
711
803
result = GitBranchPushResult()
712
804
result.source_branch = self.source
713
805
result.target_branch = self.target
714
new_refs, main_ref = self._get_new_refs(stop_revision)
806
new_refs, main_ref, stop_revinfo = self._get_new_refs(stop_revision)
715
807
def update_refs(old_refs):
716
808
refs = dict(old_refs)
717
809
# FIXME: Check for diverged branches