diff --git a/ddsc/cmdparser.py b/ddsc/cmdparser.py
index f2f6ec5..456f8db 100644
--- a/ddsc/cmdparser.py
+++ b/ddsc/cmdparser.py
@@ -222,11 +222,11 @@ def _add_copy_project_arg(arg_parser):
     Adds optional copy_project parameter to a parser.
     :param arg_parser: ArgumentParser parser to add this argument to.
     """
-    arg_parser.add_argument("--skip-copy",
-                            help="Should we just send the deliver email and skip copying the project.",
+    arg_parser.add_argument("--copy",
+                            help="Instead of delivering the specified project, deliver a copy of the project.",
                             action='store_true',
                             default=False,
-                            dest='skip_copy_project')
+                            dest='copy_project')
 
 
 def _add_resend_arg(arg_parser, resend_help):
@@ -424,8 +424,8 @@ class CommandParser(object):
         :param deliver_func: function to run when user choses this option
         """
         description = "Initiate delivery of a project to another user. Removes other user's current permissions. " \
-                      "Makes a copy of the project. Send message to D4S2 service to send email and allow " \
-                      "access to the copy of the project once user acknowledges receiving the data."
+                      "Send message to D4S2 service to send email and allow access to the project once user " \
+                      "acknowledges receiving the data."
         deliver_parser = self.subparsers.add_parser('deliver', description=description)
         add_project_name_or_id_arg(deliver_parser)
         user_or_email = deliver_parser.add_mutually_exclusive_group(required=True)
diff --git a/ddsc/core/download.py b/ddsc/core/download.py
index 914f348..f9bf81b 100644
--- a/ddsc/core/download.py
+++ b/ddsc/core/download.py
@@ -84,7 +84,7 @@ class ProjectDownload(object):
         :param files_to_download: [ProjectFile]: files that will be downloaded
         """
         for project_file in files_to_download:
-            self.file_download_pre_processor.run(project_file)
+            self.file_download_pre_processor.run(self.remote_store.data_service, project_file)
 
     def download_files(self, files_to_download, watcher):
         settings = DownloadSettings(self.remote_store, self.dest_directory, watcher)
diff --git a/ddsc/ddsclient.py b/ddsc/ddsclient.py
index ccd7307..2b2eb4e 100644
--- a/ddsc/ddsclient.py
+++ b/ddsc/ddsclient.py
@@ -309,7 +309,7 @@ class DeliverCommand(BaseCommand):
         """
         email = args.email                  # email of person to deliver to, will be None if username is specified
         username = args.username            # username of person to deliver to, will be None if email is specified
-        skip_copy_project = args.skip_copy_project  # should we skip the copy step
+        copy_project = args.copy_project    # should we deliver a copy of the project
         force_send = args.resend            # is this a resend so we should force sending
         msg_file = args.msg_file            # message file who's contents will be sent with the delivery
         share_usernames = args.share_usernames  # usernames who will have this project shared once it is accepted
@@ -319,7 +319,7 @@ class DeliverCommand(BaseCommand):
         share_users = self.make_user_list(share_emails, share_usernames)
         print("Delivering project.")
         new_project_name = None
-        if not skip_copy_project:
+        if copy_project:
             new_project_name = self.get_new_project_name(project.name)
         to_user = self.remote_store.lookup_or_register_user_by_email_or_username(email, username)
         try:

Should --skip-copy be the default?
I want to revisit this choice. When delivering data, it's certainly unexpected that ddsclient will download the entire project and upload a copy. I'll reach out to the users but it may be a better default to skip the copy, and require a `--copy` argument to make a copy before delivering.
diff --git a/ddsc/core/tests/test_download.py b/ddsc/core/tests/test_download.py
index 4bb4a0d..4fa9275 100644
--- a/ddsc/core/tests/test_download.py
+++ b/ddsc/core/tests/test_download.py
@@ -101,8 +101,8 @@ class TestProjectDownload(TestCase):
         mock_file2 = Mock(path='file2.txt')
         project_download.run_preprocessor([mock_file1, mock_file2])
         mock_preprocessor.run.assert_has_calls([
-            call(mock_file1),
-            call(mock_file2)
+            call(self.mock_remote_store.data_service, mock_file1),
+            call(self.mock_remote_store.data_service, mock_file2)
         ])
 
 
diff --git a/ddsc/tests/test_cmdparser.py b/ddsc/tests/test_cmdparser.py
index 243b7f4..e521d0d 100644
--- a/ddsc/tests/test_cmdparser.py
+++ b/ddsc/tests/test_cmdparser.py
@@ -57,6 +57,7 @@ class TestCommandParser(TestCase):
         self.assertEqual(None, self.parsed_args.project_id)
         self.assertEqual(None, self.parsed_args.share_usernames)
         self.assertEqual(None, self.parsed_args.share_emails)
+        self.assertEqual(False, self.parsed_args.copy_project)
 
     def test_deliver_with_msg(self):
         command_parser = CommandParser(version_str='1.0')
@@ -66,6 +67,7 @@ class TestCommandParser(TestCase):
         self.assertIn('setup(', self.parsed_args.msg_file.read())
         self.assertEqual(None, self.parsed_args.project_name)
         self.assertEqual('123', self.parsed_args.project_id)
+        self.assertEqual(False, self.parsed_args.copy_project)
 
     def test_deliver_with_share_users(self):
         command_parser = CommandParser(version_str='1.0')
@@ -79,6 +81,19 @@ class TestCommandParser(TestCase):
         self.assertEqual('123', self.parsed_args.project_id)
         self.assertEqual(['bob555', 'tom666'], self.parsed_args.share_usernames)
         self.assertEqual(['bob@bob.bob'], self.parsed_args.share_emails)
+        self.assertEqual(False, self.parsed_args.copy_project)
+
+    def test_deliver_with_copy(self):
+        command_parser = CommandParser(version_str='1.0')
+        command_parser.register_deliver_command(self.set_parsed_args)
+        self.assertEqual(['deliver'], list(command_parser.subparsers.choices.keys()))
+        command_parser.run_command(['deliver', '-p', 'someproject', '--user', 'joe123', '--copy'])
+        self.assertEqual(None, self.parsed_args.msg_file)
+        self.assertEqual('someproject', self.parsed_args.project_name)
+        self.assertEqual(None, self.parsed_args.project_id)
+        self.assertEqual(None, self.parsed_args.share_usernames)
+        self.assertEqual(None, self.parsed_args.share_emails)
+        self.assertEqual(True, self.parsed_args.copy_project)
 
     def test_share_no_msg(self):
         command_parser = CommandParser(version_str='1.0')
diff --git a/ddsc/tests/test_ddsclient.py b/ddsc/tests/test_ddsclient.py
index b6fe028..7a33cf5 100644
--- a/ddsc/tests/test_ddsclient.py
+++ b/ddsc/tests/test_ddsclient.py
@@ -177,8 +177,10 @@ class TestShareCommand(TestCase):
 class TestDeliverCommand(TestCase):
     @patch('ddsc.ddsclient.RemoteStore')
     @patch('ddsc.ddsclient.D4S2Project')
-    def test_run_no_message(self, mock_d4s2_project, mock_remote_store):
+    def test_run_no_message_and_copy(self, mock_d4s2_project, mock_remote_store):
         cmd = DeliverCommand(MagicMock())
+        cmd.get_new_project_name = Mock()
+        cmd.get_new_project_name.return_value = 'NewProjectName'
         myargs = Mock(project_name='mouse',
                       project_id=None,
                       email=None,
@@ -186,7 +188,7 @@ class TestDeliverCommand(TestCase):
                       username='joe123',
                       share_usernames=[],
                       share_emails=[],
-                      skip_copy_project=True,
+                      copy_project=True,
                       include_paths=None,
                       exclude_paths=None,
                       msg_file=None)
@@ -196,6 +198,7 @@ class TestDeliverCommand(TestCase):
         self.assertEqual(project, mock_remote_store.return_value.fetch_remote_project.return_value)
         self.assertEqual(False, force_send)
         self.assertEqual('', message)
+        self.assertEqual('NewProjectName', new_project_name)
         args, kwargs = mock_remote_store.return_value.fetch_remote_project.call_args
         self.assertEqual('mouse', args[0].get_name_or_raise())
 
@@ -211,7 +214,7 @@ class TestDeliverCommand(TestCase):
                           username='joe123',
                           share_emails=[],
                           share_usernames=[],
-                          skip_copy_project=True,
+                          copy_project=False,
                           include_paths=None,
                           exclude_paths=None,
                           msg_file=message_infile)
@@ -221,6 +224,7 @@ class TestDeliverCommand(TestCase):
             self.assertEqual(project, mock_remote_store.return_value.fetch_remote_project.return_value)
             self.assertEqual(False, force_send)
             self.assertIn('setup(', message)
+            self.assertEqual(new_project_name, None)
             args, kwargs = mock_remote_store.return_value.fetch_remote_project.call_args
             self.assertEqual('456', args[0].get_id_or_raise())
 

pip install -e .[dev]
parse_log_pytest
requirements.txt
pytest
3.7
requirements.txt devRequirements.txt
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
certifi @ file:///croot/certifi_1671487769961/work/certifi
-e git+https://github.com/Duke-GCB/DukeDSClient.git@b8274d3185ec78ca47a772c1fb644ba319dedd80#egg=DukeDSClient
exceptiongroup==1.2.2
flake8==3.3.0
future==0.16.0
importlib-metadata==6.7.0
iniconfig==2.0.0
mccabe==0.6.1
mock==2.0.0
nose==1.3.7
packaging==24.0
pbr==6.1.1
pluggy==1.2.0
pycodestyle==2.3.1
pyflakes==1.5.0
pytest==7.4.4
pytz==2025.2
PyYAML==3.12
requests==2.13.0
six==1.10.0
tomli==2.0.1
typing_extensions==4.7.1
zipp==3.15.0

name: DukeDSClient
channels:
  - defaults
  - https://repo.anaconda.com/pkgs/main
  - https://repo.anaconda.com/pkgs/r
  - conda-forge
dependencies:
  - _libgcc_mutex=0.1=main
  - _openmp_mutex=5.1=1_gnu
  - ca-certificates=2025.2.25=h06a4308_0
  - certifi=2022.12.7=py37h06a4308_0
  - ld_impl_linux-64=2.40=h12ee557_0
  - libffi=3.4.4=h6a678d5_1
  - libgcc-ng=11.2.0=h1234567_1
  - libgomp=11.2.0=h1234567_1
  - libstdcxx-ng=11.2.0=h1234567_1
  - ncurses=6.4=h6a678d5_0
  - openssl=1.1.1w=h7f8727e_0
  - pip=22.3.1=py37h06a4308_0
  - python=3.7.16=h7a1cb2a_0
  - readline=8.2=h5eee18b_0
  - setuptools=65.6.3=py37h06a4308_0
  - sqlite=3.45.3=h5eee18b_0
  - tk=8.6.14=h39e8969_0
  - wheel=0.38.4=py37h06a4308_0
  - xz=5.6.4=h5eee18b_1
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - exceptiongroup==1.2.2
      - flake8==3.3.0
      - future==0.16.0
      - importlib-metadata==6.7.0
      - iniconfig==2.0.0
      - mccabe==0.6.1
      - mock==2.0.0
      - nose==1.3.7
      - packaging==24.0
      - pbr==6.1.1
      - pluggy==1.2.0
      - pycodestyle==2.3.1
      - pyflakes==1.5.0
      - pytest==7.4.4
      - pytz==2025.2
      - pyyaml==3.12
      - requests==2.13.0
      - six==1.10.0
      - tomli==2.0.1
      - typing-extensions==4.7.1
      - zipp==3.15.0
prefix: /opt/conda/envs/DukeDSClient

ddsc/core/tests/test_download.py::TestProjectDownload::test_run_preprocessor ddsc/tests/test_cmdparser.py::TestCommandParser::test_deliver_no_msg ddsc/tests/test_cmdparser.py::TestCommandParser::test_deliver_with_copy ddsc/tests/test_cmdparser.py::TestCommandParser::test_deliver_with_msg ddsc/tests/test_cmdparser.py::TestCommandParser::test_deliver_with_share_users ddsc/tests/test_ddsclient.py::TestDeliverCommand::test_run_no_message_and_copy
ddsc/core/tests/test_download.py::TestProjectDownload::test_check_warnings ddsc/core/tests/test_download.py::TestProjectDownload::test_include_project_file ddsc/core/tests/test_download.py::TestProjectDownload::test_run ddsc/core/tests/test_download.py::TestDownloadSettings::test_get_data_service_auth_data ddsc/core/tests/test_download.py::TestDownloadContext::test_create_data_service ddsc/core/tests/test_download.py::TestDownloadContext::test_create_remote_store ddsc/core/tests/test_download.py::TestDownloadContext::test_send_error_message ddsc/core/tests/test_download.py::TestDownloadContext::test_send_message ddsc/core/tests/test_download.py::TestDownloadContext::test_send_processed_message ddsc/core/tests/test_download.py::TestFileUrlDownloader::test_check_downloaded_files_sizes ddsc/core/tests/test_download.py::TestFileUrlDownloader::test_check_file_size ddsc/core/tests/test_download.py::TestFileUrlDownloader::test_determine_bytes_per_chunk ddsc/core/tests/test_download.py::TestFileUrlDownloader::test_download_files ddsc/core/tests/test_download.py::TestFileUrlDownloader::test_make_big_empty_files ddsc/core/tests/test_download.py::TestFileUrlDownloader::test_make_local_directories ddsc/core/tests/test_download.py::TestFileUrlDownloader::test_make_ranges ddsc/core/tests/test_download.py::TestFileUrlDownloader::test_split_file_urls_by_size ddsc/core/tests/test_download.py::TestDownloadFilePartCommand::test_create_context ddsc/core/tests/test_download.py::TestDownloadFilePartCommand::test_on_message_error ddsc/core/tests/test_download.py::TestDownloadFilePartCommand::test_on_message_processed ddsc/core/tests/test_download.py::TestDownloadFilePartRun::test_download_file_part_run ddsc/core/tests/test_download.py::TestRetryChunkDownloader::test_download_chunk_inconsistent ddsc/core/tests/test_download.py::TestRetryChunkDownloader::test_download_chunk_works ddsc/core/tests/test_download.py::TestRetryChunkDownloader::test_get_range_headers ddsc/core/tests/test_download.py::TestRetryChunkDownloader::test_get_url_and_headers_for_range ddsc/core/tests/test_download.py::TestRetryChunkDownloader::test_on_bytes_read ddsc/core/tests/test_download.py::TestRetryChunkDownloader::test_on_bytes_read_too_much ddsc/core/tests/test_download.py::TestRetryChunkDownloader::test_retry_download_loop ddsc/core/tests/test_download.py::TestRetryChunkDownloader::test_retry_download_loop_raises_when_out_of_retries ddsc/core/tests/test_download.py::TestRetryChunkDownloader::test_retry_download_loop_retries_then_works ddsc/core/tests/test_download.py::TestRetryChunkDownloader::test_run_handles_exception ddsc/core/tests/test_download.py::TestRetryChunkDownloader::test_verify_download_complete_ok ddsc/core/tests/test_download.py::TestRetryChunkDownloader::test_verify_download_complete_partial ddsc/core/tests/test_download.py::TestRetryChunkDownloader::test_verify_download_complete_too_large ddsc/tests/test_cmdparser.py::TestCommandParser::test_description ddsc/tests/test_cmdparser.py::TestCommandParser::test_format_destination_path_ok_when_dir_empty ddsc/tests/test_cmdparser.py::TestCommandParser::test_list_command ddsc/tests/test_cmdparser.py::TestCommandParser::test_list_command_long ddsc/tests/test_cmdparser.py::TestCommandParser::test_register_add_user_command_project_id ddsc/tests/test_cmdparser.py::TestCommandParser::test_register_add_user_command_project_name ddsc/tests/test_cmdparser.py::TestCommandParser::test_register_download_command ddsc/tests/test_cmdparser.py::TestCommandParser::test_register_remove_user_command_project_id ddsc/tests/test_cmdparser.py::TestCommandParser::test_register_remove_user_command_project_name ddsc/tests/test_cmdparser.py::TestCommandParser::test_share_no_msg ddsc/tests/test_cmdparser.py::TestCommandParser::test_share_with_msg ddsc/tests/test_ddsclient.py::TestBaseCommand::test_fetch_project ddsc/tests/test_ddsclient.py::TestBaseCommand::test_make_user_list ddsc/tests/test_ddsclient.py::TestBaseCommand::test_project_name_or_id_from_args ddsc/tests/test_ddsclient.py::TestUploadCommand::test_with_dry_run ddsc/tests/test_ddsclient.py::TestUploadCommand::test_without_dry_run ddsc/tests/test_ddsclient.py::TestUploadCommand::test_without_dry_run_project_id ddsc/tests/test_ddsclient.py::TestDownloadCommand::test_run_project_id ddsc/tests/test_ddsclient.py::TestDownloadCommand::test_run_project_name ddsc/tests/test_ddsclient.py::TestShareCommand::test_run_message ddsc/tests/test_ddsclient.py::TestShareCommand::test_run_no_message ddsc/tests/test_ddsclient.py::TestDeliverCommand::test_run_message ddsc/tests/test_ddsclient.py::TestDDSClient::test_read_argument_file_contents ddsc/tests/test_ddsclient.py::TestListCommand::test_get_project_info_line ddsc/tests/test_ddsclient.py::TestListCommand::test_pprint_project_list_details_with_auth_role ddsc/tests/test_ddsclient.py::TestListCommand::test_print_project_list_details ddsc/tests/test_ddsclient.py::TestListCommand::test_print_project_list_details_long_format ddsc/tests/test_ddsclient.py::TestListCommand::test_print_project_list_details_with_auth_role_long_format
ddsc/core/download.py ddsc/cmdparser.py ddsc/ddsclient.py
ddsc/core/download.py ddsc/cmdparser.py ddsc/ddsclient.py