Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 14 additions & 1 deletion dvc/commands/data_sync.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ def run(self):
all_branches=self.args.all_branches,
all_tags=self.args.all_tags,
all_commits=self.args.all_commits,
num=self.args.num,
with_deps=self.args.with_deps,
recursive=self.args.recursive,
run_cache=self.args.run_cache,
Expand Down Expand Up @@ -135,7 +136,7 @@ def shared_parent_parser():
return parent_parser


def add_parser(subparsers, _parent_parser):
def add_parser(subparsers, _parent_parser): # noqa: PLR0915
from dvc.commands.status import CmdDataStatus

# Pull
Expand Down Expand Up @@ -309,6 +310,18 @@ def add_parser(subparsers, _parent_parser):
default=False,
help="Fetch cache for all commits.",
)
fetch_parser.add_argument(
"--num",
type=int,
default=1,
dest="num",
metavar="<number>",
help=(
"Fetch cache for the last `num` commits. Defaults to the current "
"branch when used on its own, or applies to each branch with "
"`--all-branches`."
),
)
fetch_parser.add_argument(
"-d",
"--with-deps",
Expand Down
13 changes: 12 additions & 1 deletion dvc/repo/fetch.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from typing import TYPE_CHECKING

from dvc.exceptions import DownloadError
from dvc.exceptions import DownloadError, InvalidArgumentError
from dvc.log import logger
from dvc.stage.cache import RunCacheNotSupported
from dvc.ui import ui
Expand Down Expand Up @@ -35,6 +35,7 @@ def _collect_indexes( # noqa: PLR0913
recursive=False,
all_commits=False,
revs=None,
num=1,
workspace=True,
max_size=None,
types=None,
Expand Down Expand Up @@ -66,6 +67,7 @@ def outs_filter(out: "Output") -> bool:
all_branches=all_branches,
all_tags=all_tags,
all_commits=all_commits,
num=num,
workspace=workspace,
):
try:
Expand Down Expand Up @@ -110,6 +112,7 @@ def fetch( # noqa: PLR0913
all_commits=False,
run_cache=False,
revs=None,
num=1,
workspace=True,
max_size=None,
types=None,
Expand All @@ -136,6 +139,13 @@ def fetch( # noqa: PLR0913
if isinstance(targets, str):
targets = [targets]

if num < 1:
raise InvalidArgumentError("`--num` must be a positive integer.")

if num > 1 and not (revs or all_branches or all_tags or all_commits):
# `--num` on its own fetches the last `num` commits of the current branch.
revs = ["HEAD"]

failed_count = 0
transferred_count = 0

Expand All @@ -157,6 +167,7 @@ def fetch( # noqa: PLR0913
recursive=recursive,
all_commits=all_commits,
revs=revs,
num=num,
workspace=workspace,
max_size=max_size,
types=types,
Expand Down
30 changes: 30 additions & 0 deletions tests/func/test_data_cloud.py
Original file line number Diff line number Diff line change
Expand Up @@ -537,6 +537,36 @@ def test_push_pull_all(tmp_dir, scm, dvc, local_remote, key, expected):
}


def test_fetch_num(tmp_dir, scm, dvc, local_remote):
# Three commits, each tracking a distinct version (hash) of the same file.
tmp_dir.dvc_gen("foo", "first", commit="first")
tmp_dir.dvc_gen("foo", "second", commit="second")
tmp_dir.dvc_gen("foo", "third", commit="third")

assert dvc.push(all_commits=True) == 3

# `--num` on its own fetches the last `num` commits of the current branch:
# HEAD ("third") and HEAD~1 ("second"), but not HEAD~2 ("first").
clean(["foo"], dvc)
assert dvc.fetch(num=2) == 2

# default (`num=1`) only fetches the workspace revision ("third").
clean(["foo"], dvc)
assert dvc.fetch() == 1

# `--num` larger than history is capped at the available commits.
clean(["foo"], dvc)
assert dvc.fetch(num=10) == 3


def test_fetch_num_invalid(tmp_dir, dvc, local_remote):
from dvc.exceptions import InvalidArgumentError

tmp_dir.dvc_gen({"foo": "foo"})
with pytest.raises(InvalidArgumentError):
dvc.fetch(num=0)


def test_push_pull_fetch_pipeline_stages(tmp_dir, dvc, run_copy, local_remote):
tmp_dir.dvc_gen("foo", "foo")
run_copy("foo", "bar", name="copy-foo-bar")
Expand Down
3 changes: 3 additions & 0 deletions tests/unit/command/test_data_sync.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ def test_fetch(mocker, dvc):
"--all-branches",
"--all-tags",
"--all-commits",
"--num",
"2",
"--with-deps",
"--recursive",
"--run-cache",
Expand All @@ -40,6 +42,7 @@ def test_fetch(mocker, dvc):
all_branches=True,
all_tags=True,
all_commits=True,
num=2,
with_deps=True,
recursive=True,
run_cache=True,
Expand Down
Loading