111
114
return self._lookup_revno(self.new_revid)
114
class GitTags(tag.BasicTags):
115
"""Ref-based tag dictionary."""
117
def __init__(self, branch):
119
self.repository = branch.repository
121
def _merge_to_remote_git(self, target_repo, source_tag_refs,
117
class InterTagsFromGitToRemoteGit(InterTags):
120
def is_compatible(klass, source, target):
121
if not isinstance(source, GitTags):
123
if not isinstance(target, GitTags):
125
if getattr(target.branch.repository, "_git", None) is not None:
129
def merge(self, overwrite=False, ignore_master=False, selector=None):
130
if self.source.branch.repository.has_same_location(self.target.branch.repository):
134
source_tag_refs = self.source.branch.get_tag_refs()
126
136
def get_changed_refs(old_refs):
127
137
ret = dict(old_refs)
128
138
for ref_name, tag_name, peeled, unpeeled in (
129
139
source_tag_refs.iteritems()):
140
if selector and not selector(tag_name):
130
142
if old_refs.get(ref_name) == unpeeled:
132
144
elif overwrite or ref_name not in old_refs:
133
145
ret[ref_name] = unpeeled
134
updates[tag_name] = target_repo.lookup_foreign_revision_id(
146
updates[tag_name] = self.target.branch.repository.lookup_foreign_revision_id(
148
self.target.branch._tag_refs = None
137
150
conflicts.append(
139
152
self.repository.lookup_foreign_revision_id(peeled),
140
target_repo.lookup_foreign_revision_id(
153
self.target.branch.repository.lookup_foreign_revision_id(
141
154
old_refs[ref_name])))
143
target_repo.controldir.send_pack(
156
self.target.branch.repository.controldir.send_pack(
144
157
get_changed_refs, lambda have, want: [])
145
return updates, conflicts
147
def _merge_to_local_git(self, target_repo, source_tag_refs,
158
return updates, set(conflicts)
161
class InterTagsFromGitToLocalGit(InterTags):
164
def is_compatible(klass, source, target):
165
if not isinstance(source, GitTags):
167
if not isinstance(target, GitTags):
169
if getattr(target.branch.repository, "_git", None) is None:
173
def merge(self, overwrite=False, ignore_master=False, selector=None):
174
if self.source.branch.repository.has_same_location(self.target.branch.repository):
179
source_tag_refs = self.source.branch.get_tag_refs()
181
target_repo = self.target.branch.repository
151
183
for ref_name, tag_name, peeled, unpeeled in source_tag_refs:
184
if selector and not selector(tag_name):
152
186
if target_repo._git.refs.get(ref_name) == unpeeled:
154
188
elif overwrite or ref_name not in target_repo._git.refs:
181
216
conflicts.append((tag_name, source_revid, target_revid))
182
return updates, conflicts
184
def _merge_to_git(self, to_tags, source_tag_refs, overwrite=False):
185
target_repo = to_tags.repository
186
if self.repository.has_same_location(target_repo):
189
if getattr(target_repo, "_git", None):
190
return self._merge_to_local_git(
191
target_repo, source_tag_refs, overwrite)
193
return self._merge_to_remote_git(
194
target_repo, source_tag_refs, overwrite)
196
to_tags.branch._tag_refs = None
198
def _merge_to_non_git(self, to_tags, source_tag_refs, overwrite=False):
217
return updates, set(conflicts)
220
class InterTagsFromGitToNonGit(InterTags):
223
def is_compatible(klass, source, target):
224
if not isinstance(source, GitTags):
226
if isinstance(target, GitTags):
230
def merge(self, overwrite=False, ignore_master=False, selector=None):
231
"""See Tags.merge_to."""
232
source_tag_refs = self.source.branch.get_tag_refs()
236
master = self.target.branch.get_master_branch()
237
with contextlib.ExitStack() as es:
238
if master is not None:
239
es.enter_context(master.lock_write())
240
updates, conflicts = self._merge_to(
241
self.target, source_tag_refs, overwrite=overwrite,
243
if master is not None:
244
extra_updates, extra_conflicts = self._merge_to(
245
master.tags, overwrite=overwrite,
246
source_tag_refs=source_tag_refs,
247
ignore_master=ignore_master, selector=selector)
248
updates.update(extra_updates)
249
conflicts.update(extra_conflicts)
250
return updates, conflicts
252
def _merge_to(self, to_tags, source_tag_refs, overwrite=False,
199
254
unpeeled_map = defaultdict(set)
202
257
result = dict(to_tags.get_tag_dict())
203
258
for ref_name, tag_name, peeled, unpeeled in source_tag_refs:
259
if selector and not selector(tag_name):
204
261
if unpeeled is not None:
205
262
unpeeled_map[peeled].add(unpeeled)
207
bzr_revid = self.branch.lookup_foreign_revision_id(peeled)
264
bzr_revid = self.source.branch.lookup_foreign_revision_id(peeled)
208
265
except NotCommitError:
210
267
if result.get(tag_name) == bzr_revid:
219
276
map_file = UnpeelMap.from_repository(to_tags.branch.repository)
220
277
map_file.update(unpeeled_map)
221
278
map_file.save_in_repository(to_tags.branch.repository)
222
return updates, conflicts
224
def merge_to(self, to_tags, overwrite=False, ignore_master=False,
225
source_tag_refs=None):
226
"""See Tags.merge_to."""
227
if source_tag_refs is None:
228
source_tag_refs = self.branch.get_tag_refs()
231
if isinstance(to_tags, GitTags):
232
return self._merge_to_git(to_tags, source_tag_refs,
238
master = to_tags.branch.get_master_branch()
239
with contextlib.ExitStack() as es:
240
if master is not None:
241
es.enter_context(master.lock_write())
242
updates, conflicts = self._merge_to_non_git(
243
to_tags, source_tag_refs, overwrite=overwrite)
244
if master is not None:
245
extra_updates, extra_conflicts = self.merge_to(
246
master.tags, overwrite=overwrite,
247
source_tag_refs=source_tag_refs,
248
ignore_master=ignore_master)
249
updates.update(extra_updates)
250
conflicts += extra_conflicts
251
return updates, conflicts
279
return updates, set(conflicts)
282
InterTags.register_optimiser(InterTagsFromGitToRemoteGit)
283
InterTags.register_optimiser(InterTagsFromGitToLocalGit)
284
InterTags.register_optimiser(InterTagsFromGitToNonGit)
288
"""Ref-based tag dictionary."""
290
def __init__(self, branch):
292
self.repository = branch.repository
253
294
def get_tag_dict(self):
612
662
return revision.NULL_REVISION
613
663
return self.lookup_foreign_revision_id(self.head)
615
def _basic_push(self, target, overwrite=False, stop_revision=None):
665
def _basic_push(self, target, overwrite=False, stop_revision=None,
616
667
return branch.InterBranch.get(self, target)._basic_push(
617
overwrite, stop_revision)
668
overwrite, stop_revision, tag_selector=tag_selector)
619
670
def lookup_foreign_revision_id(self, foreign_revid):
934
985
stop_revision, fetch_tags=fetch_tags, limit=limit, lossy=lossy)
935
986
return _mod_repository.FetchResult()
937
def fetch_objects(self, stop_revision, fetch_tags, limit=None, lossy=False):
988
def fetch_objects(self, stop_revision, fetch_tags, limit=None, lossy=False, tag_selector=None):
938
989
interrepo = self._get_interrepo(self.source, self.target)
939
990
if fetch_tags is None:
940
991
c = self.source.get_config_stack()
953
1004
self._last_revid = stop_revision
954
1005
real = interrepo.get_determine_wants_revids(
955
[self._last_revid], include_tags=fetch_tags)
1006
[self._last_revid], include_tags=fetch_tags, tag_selector=tag_selector)
956
1007
return real(heads)
957
1008
pack_hint, head, refs = interrepo.fetch_objects(
958
1009
determine_wants, self.source.mapping, limit=limit,
962
1013
self.target.repository.pack(hint=pack_hint)
963
1014
return head, refs
965
def _update_revisions(self, stop_revision=None, overwrite=False):
966
head, refs = self.fetch_objects(stop_revision, fetch_tags=None)
1016
def _update_revisions(self, stop_revision=None, overwrite=False, tag_selector=None):
1017
head, refs = self.fetch_objects(stop_revision, fetch_tags=None, tag_selector=tag_selector)
968
1019
prev_last_revid = None
1005
1056
(result.old_revno, result.old_revid) = \
1006
1057
self.target.last_revision_info()
1007
1058
result.new_git_head, remote_refs = self._update_revisions(
1008
stop_revision, overwrite=("history" in overwrite))
1059
stop_revision, overwrite=("history" in overwrite),
1060
tag_selector=tag_selector)
1009
1061
tags_ret = self.source.tags.merge_to(
1010
1062
self.target.tags, ("tags" in overwrite), ignore_master=True)
1011
1063
if isinstance(tags_ret, tuple):
1029
1081
def pull(self, overwrite=False, stop_revision=None,
1030
1082
possible_transports=None, _hook_master=None, run_hooks=True,
1031
_override_hook_target=None, local=False):
1083
_override_hook_target=None, local=False, tag_selector=None):
1032
1084
"""See Branch.pull.
1034
1086
:param _hook_master: Private parameter - set the branch to
1066
1118
master_branch = None
1067
1119
return self._basic_pull(stop_revision, overwrite, run_hooks,
1068
1120
_override_hook_target,
1069
_hook_master=master_branch)
1121
_hook_master=master_branch,
1122
tag_selector=tag_selector)
1071
def _basic_push(self, overwrite, stop_revision):
1124
def _basic_push(self, overwrite, stop_revision, tag_selector=None):
1072
1125
if overwrite is True:
1073
1126
overwrite = set(["history", "tags"])
1074
1127
elif not overwrite:
1078
1131
result.target_branch = self.target
1079
1132
result.old_revno, result.old_revid = self.target.last_revision_info()
1080
1133
result.new_git_head, remote_refs = self._update_revisions(
1081
stop_revision, overwrite=("history" in overwrite))
1134
stop_revision, overwrite=("history" in overwrite),
1135
tag_selector=tag_selector)
1082
1136
tags_ret = self.source.tags.merge_to(
1083
self.target.tags, "tags" in overwrite, ignore_master=True)
1137
self.target.tags, "tags" in overwrite, ignore_master=True,
1138
selector=tag_selector)
1084
1139
(result.tag_updates, result.tag_conflicts) = tags_ret
1085
1140
result.new_revno, result.new_revid = self.target.last_revision_info()
1086
1141
self.update_references(revid=result.new_revid)
1109
1164
return (isinstance(source, LocalGitBranch) and
1110
1165
isinstance(target, RemoteGitBranch))
1112
def _basic_push(self, overwrite, stop_revision):
1167
def _basic_push(self, overwrite, stop_revision, tag_selector=None):
1113
1168
result = GitBranchPushResult()
1114
1169
result.source_branch = self.source
1115
1170
result.target_branch = self.target
1218
1275
return result.refs, stop_revision
1220
1277
def pull(self, stop_revision=None, overwrite=False,
1221
possible_transports=None, run_hooks=True, local=False):
1278
possible_transports=None, run_hooks=True, local=False,
1222
1280
# This type of branch can't be bound.
1224
1282
raise errors.LocalRequiresBoundBranch()
1307
1365
refs[ref] = (None, revid)
1308
1366
return refs, main_ref, (stop_revno, stop_revision)
1310
def _update_refs(self, result, old_refs, new_refs, overwrite):
1368
def _update_refs(self, result, old_refs, new_refs, overwrite, tag_selector):
1311
1369
mutter("updating refs. old refs: %r, new refs: %r",
1312
1370
old_refs, new_refs)
1313
1371
result.tag_updates = {}
1381
1441
for (old_revid, (new_sha, new_revid)) in revidmap.items()})
1383
1443
def pull(self, overwrite=False, stop_revision=None, local=False,
1384
possible_transports=None, run_hooks=True, _stop_revno=None):
1444
possible_transports=None, run_hooks=True, _stop_revno=None,
1385
1446
result = GitBranchPullResult()
1386
1447
result.source_branch = self.source
1387
1448
result.target_branch = self.target
1390
1451
stop_revision, stop_revno=_stop_revno)
1392
1453
def update_refs(old_refs):
1393
return self._update_refs(result, old_refs, new_refs, overwrite)
1454
return self._update_refs(result, old_refs, new_refs, overwrite, tag_selector)
1395
1456
result.revidmap, old_refs, new_refs = (
1396
1457
self.interrepo.fetch_refs(update_refs, lossy=False))
1412
1473
def push(self, overwrite=False, stop_revision=None, lossy=False,
1413
_override_hook_source_branch=None, _stop_revno=None):
1474
_override_hook_source_branch=None, _stop_revno=None,
1414
1476
result = GitBranchPushResult()
1415
1477
result.source_branch = self.source
1416
1478
result.target_branch = self.target
1421
1483
stop_revision, stop_revno=_stop_revno)
1423
1485
def update_refs(old_refs):
1424
return self._update_refs(result, old_refs, new_refs, overwrite)
1486
return self._update_refs(result, old_refs, new_refs, overwrite, tag_selector)
1426
1488
result.revidmap, old_refs, new_refs = (
1427
1489
self.interrepo.fetch_refs(