M dlrepo-cli => dlrepo-cli +9 -8
@@ 487,21 487,22 @@ def internal(args):
Arg("branch", metavar="BRANCH", help="the branch name"),
Arg("tag", metavar="TAG", nargs="?", help="the tag name"),
Arg("job", metavar="JOB", nargs="?", help="the job name"),
+ Arg("format", metavar="FORMAT", nargs="?", help="the artifact format"),
)
def delete(args):
"""
- Delete a job, a tag or a branch and all its tags recursively.
+ Delete a branch, a tag, a job or a format.
"""
client = HttpClient(args.url)
params = {}
+ url = os.path.join("branches", args.branch)
if args.tag:
- if args.job:
- url = os.path.join("branches", args.branch, args.tag, args.job) + "/"
- else:
- url = os.path.join("branches", args.branch, args.tag) + "/"
- else:
- url = os.path.join("branches", args.branch) + "/"
- client.delete(url, params)
+ url = os.path.join(url, args.tag)
+ if args.job:
+ url = os.path.join(url, args.job)
+ if args.format:
+ url = os.path.join(url, args.format)
+ client.delete(url + "/", params)
# --------------------------------------------------------------------------------------
M dlrepo/fs/fmt.py => dlrepo/fs/fmt.py +5 -0
@@ 229,3 229,8 @@ class ArtifactFormat(SubDir):
os.link(fpath, blob)
self.digest_path().write_text(json.dumps(new_digests, sort_keys=True))
+
+ def delete(self):
+ if not self.exists():
+ raise FileNotFoundError()
+ self.root().rmtree(self._path)
M dlrepo/fs/job.py => dlrepo/fs/job.py +1 -0
@@ 117,6 117,7 @@ class Job(SubDir):
if not d.is_symlink():
continue
if not d.is_dir():
+ d.unlink()
continue
try:
if d.resolve().samefile(self.path() / d.name):
M dlrepo/views/fmt.py => dlrepo/views/fmt.py +16 -0
@@ 2,6 2,7 @@
# Copyright (c) 2021 Robin Jarry
# SPDX-License-Identifier: BSD-3-Clause
+import asyncio
import logging
from typing import Callable
@@ 71,6 72,21 @@ class FormatDirView(BaseView):
raise web.HTTPInternalServerError(reason="post process failed") from e
return web.Response()
+ async def delete(self):
+ """
+ Delete a format.
+ """
+ loop = asyncio.get_running_loop()
+ try:
+ fmt = _get_format(self.repo(), self.request.match_info)
+ await loop.run_in_executor(None, fmt.delete)
+ self.repo().schedule_cleanup_orphans()
+ except FileNotFoundError as e:
+ raise web.HTTPNotFound() from e
+ except OSError as e:
+ raise web.HTTPBadRequest(reason=str(e)) from e
+ return web.Response()
+
# --------------------------------------------------------------------------------------
class FormatArchiveView(BaseView):
M docs/dlrepo-api.7.scdoc => docs/dlrepo-api.7.scdoc +13 -0
@@ 428,6 428,19 @@ Delete the specified _{job}_ and all its artifact formats.
- _404_: the specified _{job}_ does not exist.
- _405_: _{tag}_ is either _latest_, _stable_ or _oldstable_.
+# ARTIFACT FORMATS
+
+## DELETE /branches/{branch}/{tag}/{job}/{format}/
+## DELETE /~{user}/branches/{branch}/{tag}/{job}/{format}/
+
+Delete the specified artifact format.
+
+*Access:*
+ _d_
+*Errors:*
+ - _404_: the specified _{format}_ does not exist.
+ - _405_: _{tag}_ is either _latest_, _stable_ or _oldstable_.
+
# PRODUCTS
## GET /products/