Repository: packit/packit
Issue: propose-update fails when spec does not exist downstream

```
09:06:53.847 base_git.py       DEBUG  Running default implementation for ActionName.prepare_files.
ERROR    Specfile /home/tt/p/f/r/nyancat/nyancat.spec not found.
Traceback (most recent call last):
  File "/home/tt/g/user-cont/packit/packit/cli/utils.py", line 61, in covered_func
    func(config=config, *args, **kwargs)
  File "/home/tt/g/user-cont/packit/packit/cli/update.py", line 136, in update
    force=force,
  File "/home/tt/g/user-cont/packit/packit/api.py", line 255, in sync_release
    self.dg.set_specfile_content(self.up.specfile, full_version, comment)
  File "/home/tt/g/user-cont/packit/packit/base_git.py", line 373, in set_specfile_content
    this_changelog = self.specfile.spec_content.section("%changelog")
  File "/home/tt/g/user-cont/packit/packit/base_git.py", line 111, in specfile
    self.absolute_specfile_path, self.absolute_specfile_dir
  File "/home/tt/g/user-cont/packit/packit/distgit.py", line 137, in absolute_specfile_path
    raise PackitException(f"Specfile {self._specfile_path} not found.")
packit.exceptions.PackitException: Specfile /home/tt/p/f/r/nyancat/nyancat.spec not found.
```

I have a src-git repo and am running it on a new downstream dist-git repo - it's empty.

Changed files:
packit/distgit.py, tests/integration/test_update.py, packit/api.py, packit/base_git.py

diff --git a/packit/api.py b/packit/api.py
index d1581803..0505f50d 100644
--- a/packit/api.py
+++ b/packit/api.py
@@ -27,6 +27,7 @@ This is the official python interface for packit.
 import asyncio
 import logging
 import os
+import shutil
 import sys
 from datetime import datetime
 from pathlib import Path
@@ -241,6 +242,22 @@ class PackitAPI:
             files_to_sync = self.package_config.get_all_files_to_sync()
 
             if self.up.with_action(action=ActionName.prepare_files):
+                comment = f"- new upstream release: {full_version}"
+                try:
+                    self.dg.set_specfile_content(
+                        self.up.specfile, full_version, comment
+                    )
+                except FileNotFoundError as ex:
+                    # no downstream spec file: this is either a mistake or
+                    # there is no spec file in dist-git yet, hence warning
+                    logger.warning(
+                        f"There is not spec file downstream: {ex}, copying the one from upstream."
+                    )
+                    shutil.copy2(
+                        self.up.absolute_specfile_path,
+                        self.dg.get_absolute_specfile_path(),
+                    )
+
                 raw_sync_files = files_to_sync.get_raw_files_to_sync(
                     Path(self.up.local_project.working_dir),
                     Path(self.dg.local_project.working_dir),
@@ -251,9 +268,6 @@ class PackitAPI:
                     x for x in raw_sync_files if x.src != self.up.absolute_specfile_path
                 ]
 
-                comment = f"- new upstream release: {full_version}"
-                self.dg.set_specfile_content(self.up.specfile, full_version, comment)
-
                 sync_files(raw_sync_files)
                 if upstream_ref:
                     if self.up.with_action(action=ActionName.create_patches):
diff --git a/packit/base_git.py b/packit/base_git.py
index 38640521..9d643a39 100644
--- a/packit/base_git.py
+++ b/packit/base_git.py
@@ -85,22 +85,11 @@ class PackitRepositoryBase:
     @property
     def absolute_specfile_path(self) -> Path:
         if not self._specfile_path:
-            # TODO: we should probably have a "discovery" phase before
-            #  creating Upstream, DistGit objects
-            #       when things which we don't know are discovered
-            # possible_paths = [
-            #     Path(self.local_project.working_dir)
-            #     / f"{self.package_config.downstream_package_name}.spec",
-            # ]
-            # for path in possible_paths:
-            #     if path.exists():
-            #         self._specfile_path = str(path)
-            #         break
             self._specfile_path = Path(self.local_project.working_dir).joinpath(
                 self.package_config.specfile_path
             )
             if not self._specfile_path.exists():
-                raise PackitException(f"Specfile {self._specfile_path} not found.")
+                raise FileNotFoundError(f"Specfile {self._specfile_path} not found.")
 
         return self._specfile_path
 
diff --git a/packit/distgit.py b/packit/distgit.py
index 52b509de..31a2f3ed 100644
--- a/packit/distgit.py
+++ b/packit/distgit.py
@@ -126,15 +126,19 @@ class DistGit(PackitRepositoryBase):
                 return None
         return self._downstream_config
 
+    def get_absolute_specfile_path(self) -> Path:
+        """ provide the path, don't check it """
+        return (
+            Path(self.local_project.working_dir)
+            / f"{self.package_config.downstream_package_name}.spec"
+        )
+
     @property
     def absolute_specfile_path(self) -> Path:
         if not self._specfile_path:
-            self._specfile_path = (
-                Path(self.local_project.working_dir)
-                / f"{self.package_config.downstream_package_name}.spec"
-            )
+            self._specfile_path = self.get_absolute_specfile_path()
             if not self._specfile_path.exists():
-                raise PackitException(f"Specfile {self._specfile_path} not found.")
+                raise FileNotFoundError(f"Specfile {self._specfile_path} not found.")
         return self._specfile_path
 
     def update_branch(self, branch_name: str):
diff --git a/tests/integration/test_update.py b/tests/integration/test_update.py
index edcea85a..665bdfa7 100644
--- a/tests/integration/test_update.py
+++ b/tests/integration/test_update.py
@@ -114,6 +114,30 @@ def test_basic_local_update_direct_push(
     assert (remote_dir_clone / "README.packit").is_file()
 
 
+def test_basic_local_update_direct_push_no_dg_spec(
+    cwd_upstream, api_instance, distgit_and_remote, mock_remote_functionality_upstream
+):
+    u, d, api = api_instance
+    d.joinpath("beer.spec").unlink()
+    subprocess.check_call(
+        ["git", "commit", "-m", "remove spec", "-a"], cwd=str(d),
+    )
+    _, distgit_remote = distgit_and_remote
+    mock_spec_download_remote_s(d)
+
+    api.sync_release("master", "0.1.0", create_pr=False)
+
+    remote_dir_clone = Path(f"{distgit_remote}-clone")
+    subprocess.check_call(
+        ["git", "clone", distgit_remote, str(remote_dir_clone)],
+        cwd=str(remote_dir_clone.parent),
+    )
+
+    spec = Specfile(remote_dir_clone / "beer.spec")
+    assert spec.get_version() == "0.1.0"
+    assert (remote_dir_clone / "README.packit").is_file()
+
+
 def test_basic_local_update_from_downstream(
     cwd_upstream, api_instance, mock_remote_functionality_upstream
 ):