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
21 changes: 11 additions & 10 deletions rsconnect/bundle.py
Original file line number Diff line number Diff line change
Expand Up @@ -1401,12 +1401,10 @@ def make_quarto_manifest(
if isdir(file_or_directory):
# Directory as a Quarto project.
excludes = list(excludes or []) + [".quarto"]

project_config = quarto_inspection.get("config", {}).get("project", {})
output_dir = cast(Union[str, None], project_config.get("output-dir", None))
if output_dir:
excludes = excludes + [output_dir]

files_data = quarto_inspection.get("files", {})
files_input_data = files_data.get("input", [])
# files.input is a list of absolute paths to input (rendered)
Expand All @@ -1419,18 +1417,24 @@ def make_quarto_manifest(
for each in files_input_data:
t, _ = splitext(os.path.relpath(each, file_or_directory))
excludes = excludes + [t + ".html", t + "_files/**/*"]

# relevant files don't need to include requirements.txt file because it is
# always added to the manifest (as a buffer) from the environment contents
if environment:
excludes.append(environment.filename)

relevant_files = _create_quarto_file_list(base_dir, extra_files, excludes)
else:
# Standalone Quarto document
base_dir = dirname(file_or_directory)
file_name = basename(file_or_directory)
relevant_files = [file_name] + list(extra_files or [])
# Use the common directory of the qmd and any extra files as base_dir.
# This avoids having the subfolder appear in both base_dir and rel_path.
all_files = [file_or_directory] + extra_files
base_dir = os.path.commonpath(all_files)

# Ensure base_dir is a directory, not a file
if os.path.isfile(base_dir):
base_dir = os.path.dirname(base_dir)

# Store paths relative to base_dir
relevant_files = [os.path.relpath(p, base_dir) for p in all_files]

manifest = make_source_manifest(
app_mode,
Expand All @@ -1441,13 +1445,10 @@ def make_quarto_manifest(
env_management_py,
env_management_r,
)

if environment:
manifest_add_buffer(manifest, environment.filename, environment.contents)

for rel_path in relevant_files:
manifest_add_file(manifest, rel_path, base_dir)

return manifest, relevant_files


Expand Down
74 changes: 52 additions & 22 deletions tests/test_bundle.py
Original file line number Diff line number Diff line change
Expand Up @@ -622,6 +622,53 @@ def test_make_quarto_source_bundle_from_file(self):
},
)

def test_make_quarto_source_bundle_from_file_with_extra_files(self):
temp_proj = tempfile.mkdtemp()
nested_dir = join(temp_proj, "subdir")
os.makedirs(nested_dir)

filename = join(nested_dir, "myquarto.qmd")
with open(filename, "w") as fp:
fp.write("---\n")
fp.write("title: myquarto\n")
fp.write("engine: markdown\n")
fp.write("---\n\n")
fp.write("### This is a test\n")

extra_filename = join(nested_dir, "data.csv")
with open(extra_filename, "w") as fp:
fp.write("a,b,c\n1,2,3\n")

inspect = {
"quarto": {"version": "1.3.433"},
"engines": ["markdown"],
}

with make_quarto_source_bundle(
filename,
inspect,
AppModes.STATIC_QUARTO,
None,
[extra_filename],
[],
None,
) as bundle, tarfile.open(mode="r:gz", fileobj=bundle) as tar:
names = sorted(tar.getnames())
self.assertEqual(
names,
[
"data.csv",
"manifest.json",
"myquarto.qmd",
],
)

manifest = json.loads(tar.extractfile("manifest.json").read().decode("utf-8"))
self.assertEqual(
sorted(manifest["files"].keys()),
["data.csv", "myquarto.qmd"],
)

def test_list_files(self):
# noinspection SpellCheckingInspection
paths = [
Expand Down Expand Up @@ -1018,16 +1065,8 @@ def test_make_quarto_manifest_project_with_env(self):
def test_make_quarto_manifest_project_with_extra_files(self):
temp_proj = tempfile.mkdtemp()

# include extra_files parameter
fp = open(join(temp_proj, "a"), "w")
fp.write("This is file a\n")
fp.close()
fp = open(join(temp_proj, "b"), "w")
fp.write("This is file b\n")
fp.close()
fp = open(join(temp_proj, "c"), "w")
fp.write("This is file c\n")
fp.close()
for name, contents in [("a", "This is file a\n"), ("b", "This is file b\n"), ("c", "This is file c\n")]:
Path(temp_proj, name).write_text(contents)

manifest, _ = make_quarto_manifest(
temp_proj,
Expand All @@ -1043,25 +1082,16 @@ def test_make_quarto_manifest_project_with_extra_files(self):
None,
)

if sys.platform == "win32":
a_hash = "f4751c084b3ade4d736c6293ab8468c9"
b_hash = "4976d559975b5232cf09a10afaf8d0a8"
c_hash = "09c56e1b9e6ae34c6662717c47a7e187"
else:
a_hash = "4a3eb92956aa3e16a9f0a84a43c943e7"
b_hash = "b249e5b536d30e6282cea227f3a73669"
c_hash = "53b36f1d5b6f7fb2cfaf0c15af7ffb2d"

Comment on lines -1046 to -1054
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm a little surprised by these changes — did they fail locally with your changes?

self.assertEqual(
manifest,
{
"version": 1,
"metadata": {"appmode": "quarto-shiny"},
"quarto": {"version": "0.9.16", "engines": ["jupyter"]},
"files": {
"a": {"checksum": a_hash},
"b": {"checksum": b_hash},
"c": {"checksum": c_hash},
"a": {"checksum": mock.ANY},
"b": {"checksum": mock.ANY},
"c": {"checksum": mock.ANY},
},
},
)
Expand Down
Loading