Repository: QualiSystemsLab/colony-cli

Issue:
If remote branch is not configured, received unhandled exception
STR:
Initialize git repo locally and develop a blueprint, don't connect to remote repo yet, try to use bp validate.
Expected behavior: Message "Local repository not connected to the remote space repository"
Error:
PS C:\Users\ronid\projects\clitest\blueprints> colony bp validate test
Traceback (most recent call last):
  File "c:\users\ronid\appdata\local\programs\python\python39\lib\runpy.py", line 197, in _run_module_as_main
    return _run_code(code, main_globals, None,
  File "c:\users\ronid\appdata\local\programs\python\python39\lib\runpy.py", line 87, in _run_code
    exec(code, run_globals)
  File "C:\Users\ronid\AppData\Local\Programs\Python\Python39\Scripts\colony.exe\__main__.py", line 7, in <module>
  File "c:\users\ronid\appdata\local\programs\python\python39\lib\site-packages\colony\shell.py", line 96, in main
    command.execute()
  File "c:\users\ronid\appdata\local\programs\python\python39\lib\site-packages\colony\commands\base.py", line 38, in execute
    actions_table[action]()
  File "c:\users\ronid\appdata\local\programs\python\python39\lib\site-packages\colony\commands\bp.py", line 44, in do_validate
    repo, working_branch, temp_working_branch = figure_out_branches(branch, blueprint_name)
  File "c:\users\ronid\appdata\local\programs\python\python39\lib\site-packages\colony\branch_utils.py", line 66, in figure_out_branches
    examine_blueprint_working_branch(repo, blueprint_name=blueprint_name)
  File "c:\users\ronid\appdata\local\programs\python\python39\lib\site-packages\colony\branch_utils.py", line 28, in examine_blueprint_working_branch
    if not repo.current_branch_exists_on_remote():
  File "c:\users\ronid\appdata\local\programs\python\python39\lib\site-packages\colony\utils.py", line 38, in current_branch_exists_on_remote
    remote_branches = self._get_remote_branches_names()
  File "c:\users\ronid\appdata\local\programs\python\python39\lib\site-packages\colony\utils.py", line 108, in _get_remote_branches_names
    return [ref.remote_head for ref in self.remote().refs]
  File "c:\users\ronid\appdata\local\programs\python\python39\lib\site-packages\git\repo\base.py", line 325, in remote
    r = Remote(self, name)
  File "c:\users\ronid\appdata\local\programs\python\python39\lib\site-packages\git\remote.py", line 418, in __init__
    dir(self)
  File "c:\users\ronid\appdata\local\programs\python\python39\lib\site-packages\git\remote.py", line 430, in __getattr__
    return self._config_reader.get(attr)
  File "c:\users\ronid\appdata\local\programs\python\python39\lib\site-packages\git\config.py", line 127, in <lambda>
    return lambda *args, **kwargs: self._call_config(attr, *args, **kwargs)
  File "c:\users\ronid\appdata\local\programs\python\python39\lib\site-packages\git\config.py", line 133, in _call_config
    return getattr(self._config, method)(self._section_name, *args, **kwargs)
  File "c:\users\ronid\appdata\local\programs\python\python39\lib\site-packages\git\config.py", line 82, in assure_data_present
    return func(self, *args, **kwargs)
  File "c:\users\ronid\appdata\local\programs\python\python39\lib\configparser.py", line 781, in get
    d = self._unify_values(section, vars)
  File "c:\users\ronid\appdata\local\programs\python\python39\lib\configparser.py", line 1149, in _unify_values
    raise NoSectionError(section) from None
configparser.NoSectionError: No section: 'remote "origin"'

Discussion:

Patch:
diff --git a/colony/branch_utils.py b/colony/branch_utils.py
index 6487cc6..4d84c1b 100644
--- a/colony/branch_utils.py
+++ b/colony/branch_utils.py
@@ -66,10 +66,8 @@ def figure_out_branches(user_defined_branch, blueprint_name):
 
         except BadBlueprintRepo as e:
             working_branch = None
-            logger.warning(
-                f"Branch could not be identified/used from the working directory; "
-                f"reason: {e}. The Blueprints Repository branch attached to Colony Space will be used"
-            )
+            logger.error(f"Branch could not be identified/used from the working directory; reason: {e}.")
+            success = False
 
         # Checking if:
         # 1) User has specified not use local (specified a branch)
@@ -88,7 +86,7 @@ def figure_out_branches(user_defined_branch, blueprint_name):
                     f"(This shall include any uncommitted changes but and/or untracked files)"
                 )
             except Exception as e:
-                logger.warning(f"Was not able push your latest changes to temp branch for validation. Reason: {str(e)}")
+                logger.error(f"Was not able push your latest changes to temp branch for validation. Reason: {str(e)}")
                 success = False
 
     return repo, working_branch, temp_working_branch, stashed_flag, success
diff --git a/colony/utils.py b/colony/utils.py
index f91064f..5fa3675 100644
--- a/colony/utils.py
+++ b/colony/utils.py
@@ -24,6 +24,9 @@ class BlueprintRepo(Repo):
         if self.bare:
             raise BadBlueprintRepo("Cannot get folder tree structure. Repo is bare")
 
+        if not self.remotes:
+            raise BadBlueprintRepo("Local repository not connected to the remote space repository")
+
         self.blueprints = self._fetch_blueprints_list()
 
     def repo_has_blueprint(self, blueprint_name) -> bool:
@@ -34,21 +37,19 @@ class BlueprintRepo(Repo):
         return self.head.is_detached
 
     def current_branch_exists_on_remote(self) -> bool:
-        try:
-            local_branch_name = self.active_branch.name
-            remote_branches = self._get_remote_branches_names()
-            return local_branch_name in remote_branches
-        except Exception as e:
-            logger.error(f"Failed to get remote branches names: {str(e)}")
-            return False
+        local_branch_name = self.active_branch.name
+        remote_branches = self._get_remote_branches_names()
+        return local_branch_name in remote_branches
 
     def is_current_branch_synced(self) -> bool:
         """Check if last commit in local and remote branch is the same"""
         local_branch = self.active_branch
+        if local_branch.name not in self._get_remote_branches_names():
+            return False
+
         for remote in self.remote().refs:
             if local_branch.name == remote.remote_head:
                 return local_branch.commit.__eq__(remote.commit)
-        return False
 
     # (TODO:ddovbii): must be moved to separated class (BlueprintYamlHandler or smth)
     def get_blueprint_artifacts(self, blueprint_name: str) -> dict:
@@ -108,7 +109,10 @@ class BlueprintRepo(Repo):
         return bps
 
     def _get_remote_branches_names(self):
-        return [ref.remote_head for ref in self.remote().refs]
+        if self.remotes:
+            return [ref.remote_head for ref in self.remote().refs]
+        else:
+            return []
 
     def get_active_branch(self) -> str:
         return self._active_branch
diff --git a/version.txt b/version.txt
index c4fb769..192def2 100644
--- a/version.txt
+++ b/version.txt
@@ -1,1 +1,1 @@
-1.2.10-beta
+1.2.11-beta


Test patch:
diff --git a/tests/test_utils.py b/tests/test_utils.py
index 1bd49dc..475fc82 100644
--- a/tests/test_utils.py
+++ b/tests/test_utils.py
@@ -73,13 +73,25 @@ class TestBlueprintRepo(unittest.TestCase):
             Repo.init(wrong_dir, bare=True)
             self.assertRaises(BadBlueprintRepo, BlueprintRepo, wrong_dir)
 
+    def test_raise_on_repo_without_blueprints_dir(self):
+        with tempfile.TemporaryDirectory() as temp_dir:
+            Repo.init(temp_dir)
+            self.assertRaises(BadBlueprintRepo, BlueprintRepo, temp_dir)
+
+    def test_raise_on_repo_without_remotes(self):
+        with tempfile.TemporaryDirectory() as temp_dir:
+            Repo.init(temp_dir)
+            os.mkdir(f"{temp_dir}/blueprints")
+            self.assertRaises(BadBlueprintRepo, BlueprintRepo, temp_dir)
+
     def test_has_remote_branch(self):
         self.assertTrue(self.bp_repo.current_branch_exists_on_remote())
 
     def test_no_branch_on_remote(self):
         local_branch = "my_super_branch"
-        current = self.bp_repo.create_head(local_branch)
-        current.checkout()
+        new_branch = self.bp_repo.create_head(local_branch)
+        assert self.bp_repo.active_branch != new_branch
+        new_branch.checkout()
         self.assertFalse(self.bp_repo.current_branch_exists_on_remote())
 
     def test_is_synced(self):