Changeset View
Changeset View
Standalone View
Standalone View
swh/storage/algos/snapshot.py
Show First 20 Lines • Show All 163 Lines • ▼ Show 20 Lines | for visit in iter_origin_visits(storage, origin, order=ListOrder.DESC): | ||||
and branch.target_type == TargetType.REVISION | and branch.target_type == TargetType.REVISION | ||||
and branch.target == revision_id | and branch.target == revision_id | ||||
): # snapshot found | ): # snapshot found | ||||
yield (visit, visit_status, snapshot) | yield (visit, visit_status, snapshot) | ||||
def snapshot_resolve_alias( | def snapshot_resolve_alias( | ||||
storage: StorageInterface, snapshot_id: Sha1Git, alias_name: bytes | storage: StorageInterface, snapshot_id: Sha1Git, alias_name: bytes | ||||
) -> Optional[Tuple[List[SnapshotBranch], Optional[SnapshotBranch]]]: | ) -> Optional[SnapshotBranch]: | ||||
""" | """ | ||||
Resolve snapshot branch alias to its real target. | Transitively resolve snapshot branch alias to its real target, and return it; | ||||
ie. follows every branch that is an alias, until a branch that isn't an alias | |||||
is found. | |||||
Args: | Args: | ||||
storage: Storage instance | storage: Storage instance | ||||
snapshot_id: snapshot identifier | snapshot_id: snapshot identifier | ||||
alias_name: name of the branch alias to resolve | alias_name: name of the branch alias to resolve | ||||
Returns: | Returns: | ||||
A tuple whose first member is the list of followed branches until the alias | The first branch that isn't an alias, in the alias chain; or None if | ||||
got resolved to a branch whose target type is not an alias, and second member | there is no such branch (ie. either because of a cycle alias, or a dangling | ||||
the real targeted branch. | branch). | ||||
If a dangling branch is encountered during the resolve process, second member of | |||||
the tuple will be None. | |||||
If the target type of the tuple second member is an alias, it means that | |||||
a cycle has been detected during the resolve process. | |||||
""" | """ | ||||
snapshot = storage.snapshot_get_branches( | snapshot = storage.snapshot_get_branches( | ||||
snapshot_id, branches_from=alias_name, branches_count=1 | snapshot_id, branches_from=alias_name, branches_count=1 | ||||
) | ) | ||||
if snapshot is None: | if snapshot is None: | ||||
return None | return None | ||||
if alias_name not in snapshot["branches"]: | if alias_name not in snapshot["branches"]: | ||||
return ([], None) | return None | ||||
last_branch = snapshot["branches"][alias_name] | last_branch = snapshot["branches"][alias_name] | ||||
branches = [] | |||||
seen_aliases = {alias_name} | seen_aliases = {alias_name} | ||||
while ( | while last_branch is not None and last_branch.target_type == TargetType.ALIAS: | ||||
last_branch is not None | if last_branch.target in seen_aliases: | ||||
and last_branch.target_type == TargetType.ALIAS | return None | ||||
and last_branch.target not in seen_aliases | |||||
): | |||||
branches.append(last_branch) | |||||
alias_target = last_branch.target | alias_target = last_branch.target | ||||
snapshot = storage.snapshot_get_branches( | snapshot = storage.snapshot_get_branches( | ||||
snapshot_id, branches_from=alias_target, branches_count=1 | snapshot_id, branches_from=alias_target, branches_count=1 | ||||
) | ) | ||||
assert snapshot is not None | assert snapshot is not None | ||||
last_branch = snapshot["branches"].get(alias_target) | last_branch = snapshot["branches"].get(alias_target) | ||||
seen_aliases.add(alias_target) | seen_aliases.add(alias_target) | ||||
return (branches, last_branch) | return last_branch |