Repository: ezbz/gitlabber

Issue:
If [dest] is not given, it defaults to "None"
Hello!

If one forgets to add destination folder, below "None" folder shinanigen happens %)
We can make DEST mandatory parameter, or we can simply set specific default value.

I would argue, that former approach is better.

### Logs

```log
$ mkdir TEMP && cd TEMP
$ time gitlabber --verbose -t sometoken -u https://gitlab.some.domain -i '/Test Group**' -p
root [https://gitlab.some.domain]
└── Test Group [/Test Group]
    ├── test-project-2-archived [/Test Group/test-project-2-archived]
    └── test-project-1 [/Test Group/test-project-1]

$ time gitlabber --verbose -t sometoken -u https://gitlab.some.domain -i '/Test Group**'
2021-02-24 11:04:43,263 - gitlabber.cli - DEBUG - verbose=[True], print=[False], log level set to [10] level
2021-02-24 11:04:43,275 - gitlabber.cli - DEBUG - Reading projects tree from gitlab at [https://gitlab.some.domain]
2021-02-24 11:04:43,275 - gitlabber.gitlab_tree - DEBUG - Loading projects tree gitlab server [https://gitlab.some.domain]
2021-02-24 11:04:43,278 - urllib3.connectionpool - DEBUG - Starting new HTTPS connection (1): gitlab.some.domain:443
2021-02-24 11:04:43,536 - urllib3.connectionpool - DEBUG - https://gitlab.some.domain:443 "GET /api/v4/groups HTTP/1.1" 200 None
...
2021-02-24 11:04:58,264 - urllib3.connectionpool - DEBUG - https://gitlab.some.domain:443 "GET /api/v4/groups/67/projects HTTP/1.1" 200 None
2021-02-24 11:04:58,409 - urllib3.connectionpool - DEBUG - https://gitlab.some.domain:443 "GET /api/v4/groups/66/projects HTTP/1.1" 200 None
2021-02-24 11:04:58,413 - urllib3.connectionpool - DEBUG - Resetting dropped connection: gitlab.some.domain
2021-02-24 11:04:58,651 - urllib3.connectionpool - DEBUG - https://gitlab.some.domain:443 "GET /api/v4/groups/188/subgroups HTTP/1.1" 200 2
2021-02-24 11:04:58,834 - urllib3.connectionpool - DEBUG - https://gitlab.some.domain:443 "GET /api/v4/groups/188/projects HTTP/1.1" 200 None
2021-02-24 11:04:58,914 - urllib3.connectionpool - DEBUG - https://gitlab.some.domain:443 "GET /api/v4/groups/8/subgroups HTTP/1.1" 200 2
...
2021-02-24 11:05:20,124 - urllib3.connectionpool - DEBUG - https://gitlab.some.domain:443 "GET /api/v4/groups/161/projects HTTP/1.1" 200 None
2021-02-24 11:05:20,204 - urllib3.connectionpool - DEBUG - https://gitlab.some.domain:443 "GET /api/v4/groups/13/subgroups HTTP/1.1" 200 2
2021-02-24 11:05:20,351 - urllib3.connectionpool - DEBUG - https://gitlab.some.domain:443 "GET /api/v4/groups/13/projects HTTP/1.1" 200 None
2021-02-24 11:05:20,353 - gitlabber.gitlab_tree - DEBUG - Loading projects tree from gitlab took [-448378:55:53.28]
2021-02-24 11:05:20,355 - gitlabber.gitlab_tree - DEBUG - Fetched root node with [338] projects
2021-02-24 11:05:20,358 - gitlabber.gitlab_tree - DEBUG - Matched include path [/Test Group**] to node [/Test Group/test-project-2-archived]
2021-02-24 11:05:20,358 - gitlabber.gitlab_tree - DEBUG - Matched include path [/Test Group**] to node [/Test Group/test-project-1]
2021-02-24 11:05:20,379 - gitlabber.gitlab_tree - DEBUG - Going to clone/pull [1] groups and [2] projects
2021-02-24 11:05:20,384 - gitlabber.git - DEBUG - cloning new project None/Test Group/test-project-2-archived
2021-02-24 11:05:20,385 - git.cmd - DEBUG - Popen(['git', 'clone', '-v', 'git@gitlab.some.domain:test-group/test-project-2-archived.git', 'None/Test Group/test-project-2-archived'], cwd=/home/someuser/gitlab/TEMP, universal_newlines=True, shell=None, istream=None)
2021-02-24 11:05:21,858 - git.repo.base - DEBUG - Cmd(['git', 'clone', '-v', 'git@gitlab.some.domain:test-group/test-project-2-archived.git', 'None/Test Group/test-project-2-archived'])'s unused stdout: 
2021-02-24 11:05:21,867 - gitlabber.git - DEBUG - cloning new project None/Test Group/test-project-1
2021-02-24 11:05:21,867 - git.cmd - DEBUG - Popen(['git', 'clone', '-v', 'git@gitlab.some.domain:test-group/test-project-1.git', 'None/Test Group/test-project-1'], cwd=/home/someuser/gitlab/TEMP, universal_newlines=True, shell=None, istream=None)
2021-02-24 11:05:22,853 - git.repo.base - DEBUG - Cmd(['git', 'clone', '-v', 'git@gitlab.some.domain:test-group/test-project-1.git', 'None/Test Group/test-project-1'])'s unused stdout: 
2021-02-24 11:05:22,863 - gitlabber.git - DEBUG - Syncing projects took [None]

$ ls None/Test\ Group/
test-project-1  test-project-2-archived
```

Discussion:
codecov[bot]: # [Codecov](https://codecov.io/gh/ezbz/gitlabber/pull/51?src=pr&el=h1) Report
> Merging [#51](https://codecov.io/gh/ezbz/gitlabber/pull/51?src=pr&el=desc) (4437169) into [master](https://codecov.io/gh/ezbz/gitlabber/commit/8b4ebf63dc38a8294a350db33f36850cbc2fff81?el=desc) (8b4ebf6) will **increase** coverage by `0.03%`.
> The diff coverage is `100.00%`.

[![Impacted file tree graph](https://codecov.io/gh/ezbz/gitlabber/pull/51/graphs/tree.svg?width=650&height=150&src=pr&token=VMVB8QC7M5)](https://codecov.io/gh/ezbz/gitlabber/pull/51?src=pr&el=tree)

```diff
@@            Coverage Diff             @@
##           master      #51      +/-   ##
==========================================
+ Coverage   95.57%   95.61%   +0.03%     
==========================================
  Files           9        9              
  Lines         339      342       +3     
==========================================
+ Hits          324      327       +3     
  Misses         15       15              
```


| [Impacted Files](https://codecov.io/gh/ezbz/gitlabber/pull/51?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [gitlabber/cli.py](https://codecov.io/gh/ezbz/gitlabber/pull/51/diff?src=pr&el=tree#diff-Z2l0bGFiYmVyL2NsaS5weQ==) | `94.73% <100.00%> (+0.21%)` | :arrow_up: |

------

[Continue to review full report at Codecov](https://codecov.io/gh/ezbz/gitlabber/pull/51?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/ezbz/gitlabber/pull/51?src=pr&el=footer). Last update [8b4ebf6...4437169](https://codecov.io/gh/ezbz/gitlabber/pull/51?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).


Patch:
diff --git a/gitlabber/cli.py b/gitlabber/cli.py
index 4a378d1..350f022 100644
--- a/gitlabber/cli.py
+++ b/gitlabber/cli.py
@@ -42,6 +42,9 @@ def main():
 
     if args.print:
         tree.print_tree(args.print_format)
+    elif args.dest is None:
+        print('Please specify a destination for the gitlab tree')
+        sys.exit(1)
     else:
         tree.sync_tree(args.dest)
 
diff --git a/setup.cfg b/setup.cfg
index 1db70a0..21d076c 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -13,7 +13,7 @@ parallel = true
 # e.g. --cov-report html (or xml) for html/xml output or --junitxml junit.xml
 # in order to write a coverage file that can be read by Jenkins.
 addopts =
-    -vv --cov gitlabber --no-cov-on-fail --cov-append --cov-report term-missing --cov-report html --verbose
+    -vv --cov gitlabber --no-cov-on-fail --cov-append --cov-report term-missing --cov-report html --verbose --capture=sys
 #    In order to use xdist, the developer can add, for example, the following
 #    arguments:
 #    --dist=load --numprocesses=auto


Test patch:
diff --git a/tests/test_cli.py b/tests/test_cli.py
index dd60808..86d09f0 100644
--- a/tests/test_cli.py
+++ b/tests/test_cli.py
@@ -98,3 +98,17 @@ def test_empty_tree(mock_tree):
 
     with pytest.raises(SystemExit):
         cli.main()
+
+
+@mock.patch("gitlabber.cli.GitlabTree")
+def test_missing_dest(mock_tree, capsys):
+    args_mock = mock.Mock()
+    args_mock.return_value = Node(
+        name="test", version=None, verbose=None, include="", exclude="", url="test_url", token="test_token", method=CloneMethod.SSH, naming=FolderNaming.NAME, file=None, concurrency=1, disble_progress=True, print=False, dest=None)
+    cli.parse_args = args_mock
+    mock_tree.return_value.is_empty = mock.Mock(return_value=False)
+
+    with pytest.raises(SystemExit):
+        cli.main()
+    out, err = capsys.readouterr()
+    assert "Please specify a destination" in out