Skip to content

Commit ef1ab17

Browse files
committed
sync/_async(feat): Add AsyncHgSync sync class
why: Provide async Mercurial repository synchronization. what: - Async obtain(), get_revision(), update_repo() methods - Uses AsyncHg command class
1 parent 1d3dcee commit ef1ab17

1 file changed

Lines changed: 112 additions & 0 deletions

File tree

  • src/libvcs/sync/_async

src/libvcs/sync/_async/hg.py

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
"""Async tool to manage a local hg (Mercurial) working copy from a repository.
2+
3+
Async equivalent of :mod:`libvcs.sync.hg`.
4+
5+
Note
6+
----
7+
This is an internal API not covered by versioning policy.
8+
"""
9+
10+
from __future__ import annotations
11+
12+
import pathlib
13+
import typing as t
14+
15+
from libvcs._internal.async_run import AsyncProgressCallbackProtocol
16+
from libvcs._internal.types import StrPath
17+
from libvcs.cmd._async.hg import AsyncHg
18+
from libvcs.sync._async.base import AsyncBaseSync
19+
20+
21+
class AsyncHgSync(AsyncBaseSync):
22+
"""Async tool to manage a local hg (Mercurial) repository cloned from a remote one.
23+
24+
Async equivalent of :class:`~libvcs.sync.hg.HgSync`.
25+
26+
Examples
27+
--------
28+
>>> import asyncio
29+
>>> async def example():
30+
... repo = AsyncHgSync(
31+
... url="https://hg.example.com/repo",
32+
... path="/tmp/myrepo",
33+
... )
34+
... await repo.obtain()
35+
... await repo.update_repo()
36+
>>> # asyncio.run(example())
37+
"""
38+
39+
bin_name = "hg"
40+
schemes = ("hg", "hg+http", "hg+https", "hg+file")
41+
cmd: AsyncHg
42+
43+
def __init__(
44+
self,
45+
*,
46+
url: str,
47+
path: StrPath,
48+
progress_callback: AsyncProgressCallbackProtocol | None = None,
49+
**kwargs: t.Any,
50+
) -> None:
51+
"""Initialize async Mercurial repository manager.
52+
53+
Parameters
54+
----------
55+
url : str
56+
URL of the Mercurial repository
57+
path : str | Path
58+
Local path for the repository
59+
progress_callback : AsyncProgressCallbackProtocol, optional
60+
Async callback for progress updates
61+
"""
62+
super().__init__(
63+
url=url, path=path, progress_callback=progress_callback, **kwargs
64+
)
65+
66+
self.cmd = AsyncHg(path=path, progress_callback=self.progress_callback)
67+
68+
async def obtain(self, *args: t.Any, **kwargs: t.Any) -> None:
69+
"""Clone and update a Mercurial repository to this location asynchronously.
70+
71+
Async equivalent of :meth:`~libvcs.sync.hg.HgSync.obtain`.
72+
"""
73+
self.ensure_dir()
74+
75+
self.log.info("Cloning.")
76+
await self.cmd.clone(
77+
no_update=True,
78+
quiet=True,
79+
url=self.url,
80+
log_in_real_time=True,
81+
)
82+
await self.cmd.update(
83+
quiet=True,
84+
check_returncode=True,
85+
log_in_real_time=True,
86+
)
87+
88+
async def get_revision(self) -> str:
89+
"""Get latest revision of this mercurial repository asynchronously.
90+
91+
Async equivalent of :meth:`~libvcs.sync.hg.HgSync.get_revision`.
92+
93+
Returns
94+
-------
95+
str
96+
Current revision number
97+
"""
98+
return await self.run(["parents", "--template={rev}"])
99+
100+
async def update_repo(self, *args: t.Any, **kwargs: t.Any) -> None:
101+
"""Pull changes from remote Mercurial repository asynchronously.
102+
103+
Async equivalent of :meth:`~libvcs.sync.hg.HgSync.update_repo`.
104+
"""
105+
self.ensure_dir()
106+
107+
if not pathlib.Path(self.path / ".hg").exists():
108+
await self.obtain()
109+
await self.update_repo()
110+
else:
111+
await self.cmd.update()
112+
await self.cmd.pull(update=True)

0 commit comments

Comments
 (0)