116
119
return self._lookup_revno(self.new_revid)
119
class GitTags(tag.BasicTags):
120
"""Ref-based tag dictionary."""
122
def __init__(self, branch):
124
self.repository = branch.repository
126
def _merge_to_remote_git(self, target_repo, source_tag_refs,
122
class InterTagsFromGitToRemoteGit(InterTags):
125
def is_compatible(klass, source, target):
126
if not isinstance(source, GitTags):
128
if not isinstance(target, GitTags):
130
if getattr(target.branch.repository, "_git", None) is not None:
134
def merge(self, overwrite=False, ignore_master=False, selector=None):
135
if self.source.branch.repository.has_same_location(self.target.branch.repository):
139
source_tag_refs = self.source.branch.get_tag_refs()
131
141
def get_changed_refs(old_refs):
132
142
ret = dict(old_refs)
133
143
for ref_name, tag_name, peeled, unpeeled in (
134
144
source_tag_refs.iteritems()):
145
if selector and not selector(tag_name):
135
147
if old_refs.get(ref_name) == unpeeled:
137
149
elif overwrite or ref_name not in old_refs:
138
150
ret[ref_name] = unpeeled
139
updates[tag_name] = target_repo.lookup_foreign_revision_id(
151
updates[tag_name] = self.target.branch.repository.lookup_foreign_revision_id(
153
self.target.branch._tag_refs = None
142
155
conflicts.append(
144
157
self.repository.lookup_foreign_revision_id(peeled),
145
target_repo.lookup_foreign_revision_id(
158
self.target.branch.repository.lookup_foreign_revision_id(
146
159
old_refs[ref_name])))
148
target_repo.controldir.send_pack(
161
self.target.branch.repository.controldir.send_pack(
149
162
get_changed_refs, lambda have, want: [])
150
return updates, conflicts
152
def _merge_to_local_git(self, target_repo, source_tag_refs,
163
return updates, set(conflicts)
166
class InterTagsFromGitToLocalGit(InterTags):
169
def is_compatible(klass, source, target):
170
if not isinstance(source, GitTags):
172
if not isinstance(target, GitTags):
174
if getattr(target.branch.repository, "_git", None) is None:
178
def merge(self, overwrite=False, ignore_master=False, selector=None):
179
if self.source.branch.repository.has_same_location(self.target.branch.repository):
184
source_tag_refs = self.source.branch.get_tag_refs()
186
target_repo = self.target.branch.repository
156
188
for ref_name, tag_name, peeled, unpeeled in source_tag_refs:
189
if selector and not selector(tag_name):
157
191
if target_repo._git.refs.get(ref_name) == unpeeled:
159
193
elif overwrite or ref_name not in target_repo._git.refs:
186
221
conflicts.append((tag_name, source_revid, target_revid))
187
return updates, conflicts
189
def _merge_to_git(self, to_tags, source_tag_refs, overwrite=False):
190
target_repo = to_tags.repository
191
if self.repository.has_same_location(target_repo):
194
if getattr(target_repo, "_git", None):
195
return self._merge_to_local_git(
196
target_repo, source_tag_refs, overwrite)
198
return self._merge_to_remote_git(
199
target_repo, source_tag_refs, overwrite)
201
to_tags.branch._tag_refs = None
203
def _merge_to_non_git(self, to_tags, source_tag_refs, overwrite=False):
222
return updates, set(conflicts)
225
class InterTagsFromGitToNonGit(InterTags):
228
def is_compatible(klass, source, target):
229
if not isinstance(source, GitTags):
231
if isinstance(target, GitTags):
235
def merge(self, overwrite=False, ignore_master=False, selector=None):
236
"""See Tags.merge_to."""
237
source_tag_refs = self.source.branch.get_tag_refs()
241
master = self.target.branch.get_master_branch()
242
with cleanup.ExitStack() as es:
243
if master is not None:
244
es.enter_context(master.lock_write())
245
updates, conflicts = self._merge_to(
246
self.target, source_tag_refs, overwrite=overwrite,
248
if master is not None:
249
extra_updates, extra_conflicts = self._merge_to(
250
master.tags, overwrite=overwrite,
251
source_tag_refs=source_tag_refs,
252
ignore_master=ignore_master, selector=selector)
253
updates.update(extra_updates)
254
conflicts.update(extra_conflicts)
255
return updates, conflicts
257
def _merge_to(self, to_tags, source_tag_refs, overwrite=False,
204
259
unpeeled_map = defaultdict(set)
207
262
result = dict(to_tags.get_tag_dict())
208
263
for ref_name, tag_name, peeled, unpeeled in source_tag_refs:
264
if selector and not selector(tag_name):
209
266
if unpeeled is not None:
210
267
unpeeled_map[peeled].add(unpeeled)
212
bzr_revid = self.branch.lookup_foreign_revision_id(peeled)
269
bzr_revid = self.source.branch.lookup_foreign_revision_id(peeled)
213
270
except NotCommitError:
215
272
if result.get(tag_name) == bzr_revid:
224
281
map_file = UnpeelMap.from_repository(to_tags.branch.repository)
225
282
map_file.update(unpeeled_map)
226
283
map_file.save_in_repository(to_tags.branch.repository)
227
return updates, conflicts
229
def merge_to(self, to_tags, overwrite=False, ignore_master=False,
230
source_tag_refs=None):
231
"""See Tags.merge_to."""
232
if source_tag_refs is None:
233
source_tag_refs = self.branch.get_tag_refs()
236
if isinstance(to_tags, GitTags):
237
return self._merge_to_git(to_tags, source_tag_refs,
243
master = to_tags.branch.get_master_branch()
244
with cleanup.ExitStack() as es:
245
if master is not None:
246
es.enter_context(master.lock_write())
247
updates, conflicts = self._merge_to_non_git(
248
to_tags, source_tag_refs, overwrite=overwrite)
249
if master is not None:
250
extra_updates, extra_conflicts = self.merge_to(
251
master.tags, overwrite=overwrite,
252
source_tag_refs=source_tag_refs,
253
ignore_master=ignore_master)
254
updates.update(extra_updates)
255
conflicts += extra_conflicts
256
return updates, conflicts
284
return updates, set(conflicts)
287
InterTags.register_optimiser(InterTagsFromGitToRemoteGit)
288
InterTags.register_optimiser(InterTagsFromGitToLocalGit)
289
InterTags.register_optimiser(InterTagsFromGitToNonGit)
293
"""Ref-based tag dictionary."""
295
def __init__(self, branch):
297
self.repository = branch.repository
258
299
def get_tag_dict(self):
617
667
return revision.NULL_REVISION
618
668
return self.lookup_foreign_revision_id(self.head)
620
def _basic_push(self, target, overwrite=False, stop_revision=None):
670
def _basic_push(self, target, overwrite=False, stop_revision=None,
621
672
return branch.InterBranch.get(self, target)._basic_push(
622
overwrite, stop_revision)
673
overwrite, stop_revision, tag_selector=tag_selector)
624
675
def lookup_foreign_revision_id(self, foreign_revid):
939
990
stop_revision, fetch_tags=fetch_tags, limit=limit, lossy=lossy)
940
991
return _mod_repository.FetchResult()
942
def fetch_objects(self, stop_revision, fetch_tags, limit=None, lossy=False):
993
def fetch_objects(self, stop_revision, fetch_tags, limit=None, lossy=False, tag_selector=None):
943
994
interrepo = self._get_interrepo(self.source, self.target)
944
995
if fetch_tags is None:
945
996
c = self.source.get_config_stack()
958
1009
self._last_revid = stop_revision
959
1010
real = interrepo.get_determine_wants_revids(
960
[self._last_revid], include_tags=fetch_tags)
1011
[self._last_revid], include_tags=fetch_tags, tag_selector=tag_selector)
961
1012
return real(heads)
962
1013
pack_hint, head, refs = interrepo.fetch_objects(
963
1014
determine_wants, self.source.mapping, limit=limit,
967
1018
self.target.repository.pack(hint=pack_hint)
968
1019
return head, refs
970
def _update_revisions(self, stop_revision=None, overwrite=False):
971
head, refs = self.fetch_objects(stop_revision, fetch_tags=None)
1021
def _update_revisions(self, stop_revision=None, overwrite=False, tag_selector=None):
1022
head, refs = self.fetch_objects(stop_revision, fetch_tags=None, tag_selector=tag_selector)
973
1024
prev_last_revid = None
1010
1061
(result.old_revno, result.old_revid) = \
1011
1062
self.target.last_revision_info()
1012
1063
result.new_git_head, remote_refs = self._update_revisions(
1013
stop_revision, overwrite=("history" in overwrite))
1064
stop_revision, overwrite=("history" in overwrite),
1065
tag_selector=tag_selector)
1014
1066
tags_ret = self.source.tags.merge_to(
1015
1067
self.target.tags, ("tags" in overwrite), ignore_master=True)
1016
1068
if isinstance(tags_ret, tuple):
1034
1086
def pull(self, overwrite=False, stop_revision=None,
1035
1087
possible_transports=None, _hook_master=None, run_hooks=True,
1036
_override_hook_target=None, local=False):
1088
_override_hook_target=None, local=False, tag_selector=None):
1037
1089
"""See Branch.pull.
1039
1091
:param _hook_master: Private parameter - set the branch to
1071
1123
master_branch = None
1072
1124
return self._basic_pull(stop_revision, overwrite, run_hooks,
1073
1125
_override_hook_target,
1074
_hook_master=master_branch)
1126
_hook_master=master_branch,
1127
tag_selector=tag_selector)
1076
def _basic_push(self, overwrite, stop_revision):
1129
def _basic_push(self, overwrite, stop_revision, tag_selector=None):
1077
1130
if overwrite is True:
1078
1131
overwrite = set(["history", "tags"])
1079
1132
elif not overwrite:
1083
1136
result.target_branch = self.target
1084
1137
result.old_revno, result.old_revid = self.target.last_revision_info()
1085
1138
result.new_git_head, remote_refs = self._update_revisions(
1086
stop_revision, overwrite=("history" in overwrite))
1139
stop_revision, overwrite=("history" in overwrite),
1140
tag_selector=tag_selector)
1087
1141
tags_ret = self.source.tags.merge_to(
1088
self.target.tags, "tags" in overwrite, ignore_master=True)
1142
self.target.tags, "tags" in overwrite, ignore_master=True,
1143
selector=tag_selector)
1089
1144
(result.tag_updates, result.tag_conflicts) = tags_ret
1090
1145
result.new_revno, result.new_revid = self.target.last_revision_info()
1091
1146
self.update_references(revid=result.new_revid)
1114
1169
return (isinstance(source, LocalGitBranch) and
1115
1170
isinstance(target, RemoteGitBranch))
1117
def _basic_push(self, overwrite, stop_revision):
1172
def _basic_push(self, overwrite, stop_revision, tag_selector=None):
1118
1173
result = GitBranchPushResult()
1119
1174
result.source_branch = self.source
1120
1175
result.target_branch = self.target
1223
1280
return result.refs, stop_revision
1225
1282
def pull(self, stop_revision=None, overwrite=False,
1226
possible_transports=None, run_hooks=True, local=False):
1283
possible_transports=None, run_hooks=True, local=False,
1227
1285
# This type of branch can't be bound.
1229
1287
raise errors.LocalRequiresBoundBranch()
1312
1370
refs[ref] = (None, revid)
1313
1371
return refs, main_ref, (stop_revno, stop_revision)
1315
def _update_refs(self, result, old_refs, new_refs, overwrite):
1373
def _update_refs(self, result, old_refs, new_refs, overwrite, tag_selector):
1316
1374
mutter("updating refs. old refs: %r, new refs: %r",
1317
1375
old_refs, new_refs)
1318
1376
result.tag_updates = {}
1386
1446
for (old_revid, (new_sha, new_revid)) in revidmap.items()})
1388
1448
def pull(self, overwrite=False, stop_revision=None, local=False,
1389
possible_transports=None, run_hooks=True, _stop_revno=None):
1449
possible_transports=None, run_hooks=True, _stop_revno=None,
1390
1451
result = GitBranchPullResult()
1391
1452
result.source_branch = self.source
1392
1453
result.target_branch = self.target
1395
1456
stop_revision, stop_revno=_stop_revno)
1397
1458
def update_refs(old_refs):
1398
return self._update_refs(result, old_refs, new_refs, overwrite)
1459
return self._update_refs(result, old_refs, new_refs, overwrite, tag_selector)
1400
1461
result.revidmap, old_refs, new_refs = (
1401
1462
self.interrepo.fetch_refs(update_refs, lossy=False))
1417
1478
def push(self, overwrite=False, stop_revision=None, lossy=False,
1418
_override_hook_source_branch=None, _stop_revno=None):
1479
_override_hook_source_branch=None, _stop_revno=None,
1419
1481
result = GitBranchPushResult()
1420
1482
result.source_branch = self.source
1421
1483
result.target_branch = self.target
1426
1488
stop_revision, stop_revno=_stop_revno)
1428
1490
def update_refs(old_refs):
1429
return self._update_refs(result, old_refs, new_refs, overwrite)
1491
return self._update_refs(result, old_refs, new_refs, overwrite, tag_selector)
1431
1493
result.revidmap, old_refs, new_refs = (
1432
1494
self.interrepo.fetch_refs(