Skip to content

Commit ab85aa7

Browse files
committed
cli: introduce basic dvc du
1 parent b9092cf commit ab85aa7

File tree

4 files changed

+126
-0
lines changed

4 files changed

+126
-0
lines changed

dvc/cli/parser.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
data_sync,
2121
destroy,
2222
diff,
23+
du,
2324
experiments,
2425
freeze,
2526
gc,
@@ -91,6 +92,7 @@
9192
check_ignore,
9293
data,
9394
artifacts,
95+
du,
9496
]
9597

9698

dvc/commands/du.py

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
import argparse
2+
import logging
3+
4+
from dvc.cli import completion
5+
from dvc.cli.command import CmdBaseNoRepo
6+
from dvc.cli.utils import DictAction, append_doc_link
7+
from dvc.ui import ui
8+
9+
logger = logging.getLogger(__name__)
10+
11+
12+
class CmdDU(CmdBaseNoRepo):
13+
def run(self):
14+
from dvc.repo import Repo
15+
from dvc.utils.humanize import naturalsize
16+
17+
entries = Repo.du(
18+
self.args.url,
19+
self.args.path,
20+
rev=self.args.rev,
21+
summarize=self.args.summarize,
22+
config=self.args.config,
23+
remote=self.args.remote,
24+
remote_config=self.args.remote_config,
25+
)
26+
ui.table([(naturalsize(size), path) for path, size in entries])
27+
return 0
28+
29+
30+
def add_parser(subparsers, parent_parser):
31+
DU_HELP = "Show disk usage."
32+
du_parser = subparsers.add_parser(
33+
"du",
34+
parents=[parent_parser],
35+
description=append_doc_link(DU_HELP, "du"),
36+
help=DU_HELP,
37+
formatter_class=argparse.RawTextHelpFormatter,
38+
)
39+
du_parser.add_argument("url", help="Location of DVC repository")
40+
du_parser.add_argument(
41+
"--rev",
42+
nargs="?",
43+
help="Git revision (e.g. SHA, branch, tag)",
44+
metavar="<commit>",
45+
)
46+
du_parser.add_argument(
47+
"-s",
48+
"--summarize",
49+
action="store_true",
50+
help="Show only total du.",
51+
)
52+
du_parser.add_argument(
53+
"--config",
54+
type=str,
55+
help=(
56+
"Path to a config file that will be merged with the config "
57+
"in the target repository."
58+
),
59+
)
60+
du_parser.add_argument(
61+
"--remote",
62+
type=str,
63+
help="Remote name to set as a default in the target repository.",
64+
)
65+
du_parser.add_argument(
66+
"--remote-config",
67+
type=str,
68+
nargs="*",
69+
action=DictAction,
70+
help=(
71+
"Remote config options to merge with a remote's config (default or one "
72+
"specified by '--remote') in the target repository."
73+
),
74+
)
75+
du_parser.add_argument(
76+
"path",
77+
nargs="?",
78+
help="Path to directory within the repository",
79+
).complete = completion.DIR
80+
du_parser.set_defaults(func=CmdDU)

dvc/repo/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ class Repo:
7171
from dvc.repo.commit import commit # type: ignore[misc]
7272
from dvc.repo.destroy import destroy # type: ignore[misc]
7373
from dvc.repo.diff import diff # type: ignore[misc]
74+
from dvc.repo.du import du # type: ignore[misc]
7475
from dvc.repo.fetch import fetch # type: ignore[misc]
7576
from dvc.repo.freeze import freeze, unfreeze # type: ignore[misc]
7677
from dvc.repo.gc import gc # type: ignore[misc]

dvc/repo/du.py

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
from typing import Optional
2+
3+
4+
def du(
5+
url: str,
6+
path: Optional[str] = None,
7+
rev: Optional[str] = None,
8+
summarize: bool = False,
9+
config: Optional[str] = None,
10+
remote: Optional[str] = None,
11+
remote_config: Optional[dict] = None,
12+
):
13+
from dvc.config import Config
14+
15+
from . import Repo
16+
17+
if config and not isinstance(config, dict):
18+
config_dict = Config.load_file(config)
19+
else:
20+
config_dict = None
21+
22+
with Repo.open(
23+
url,
24+
rev=rev,
25+
subrepos=True,
26+
uninitialized=True,
27+
config=config_dict,
28+
remote=remote,
29+
remote_config=remote_config,
30+
) as repo:
31+
path = path or ""
32+
33+
fs = repo.dvcfs
34+
35+
if summarize or not fs.isdir(path):
36+
return [(path, fs.du(path, total=True))]
37+
38+
ret = [
39+
(entry_path, fs.du(entry_path, total=True))
40+
for entry_path in fs.ls(path) # pylint: disable=not-an-iterable
41+
]
42+
ret.append((path, sum(entry[1] for entry in ret)))
43+
return ret

0 commit comments

Comments
 (0)